diff options
Diffstat (limited to 'drivers/scsi/bfa')
45 files changed, 23740 insertions, 7196 deletions
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile index d2eefd3e3bd..475cf925d5e 100644 --- a/drivers/scsi/bfa/Makefile +++ b/drivers/scsi/bfa/Makefile @@ -1,8 +1,6 @@  obj-$(CONFIG_SCSI_BFA_FC) := bfa.o -bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o +bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o bfad_bsg.o  bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o  bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o -bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o - -ccflags-y := -DBFA_PERF_BUILD +bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index ff2bd07161f..4ad7e368bbc 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h @@ -17,7 +17,7 @@  #ifndef __BFA_H__  #define __BFA_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h"  #include "bfa_cs.h"  #include "bfa_plog.h"  #include "bfa_defs_svc.h" @@ -27,13 +27,12 @@  struct bfa_s;  typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m); -typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete); +typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);  /*   * Interrupt message handlers   */  void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m); -void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);  /*   * Request and response queue related defines @@ -55,7 +54,8 @@ void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);  	 ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \  		   + bfa_reqq_pi((__bfa), (__reqq))))) -#define bfa_reqq_produce(__bfa, __reqq)	do {				\ +#define bfa_reqq_produce(__bfa, __reqq, __mh)  do {			\ +		(__mh).mtag.h2i.qid     = (__bfa)->iocfc.hw_qid[__reqq];\  		(__bfa)->iocfc.req_cq_pi[__reqq]++;			\  		(__bfa)->iocfc.req_cq_pi[__reqq] &=			\  			((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \ @@ -77,16 +77,6 @@ void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);  } while (0)  /* - * Queue element to wait for room in request queue. FIFO order is - * maintained when fullfilling requests. - */ -struct bfa_reqq_wait_s { -	struct list_head	qe; -	void		(*qresume) (void *cbarg); -	void		*cbarg; -}; - -/*   * Circular queue usage assignments   */  enum { @@ -121,29 +111,18 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),  									\  		struct list_head *waitq = bfa_reqq(__bfa, __reqq);      \  									\ -		bfa_assert(((__reqq) < BFI_IOC_MAX_CQS));      \ -		bfa_assert((__wqe)->qresume && (__wqe)->cbarg);      \ +		WARN_ON(((__reqq) >= BFI_IOC_MAX_CQS));			\ +		WARN_ON(!((__wqe)->qresume && (__wqe)->cbarg));		\  									\  		list_add_tail(&(__wqe)->qe, waitq);      \  	} while (0)  #define bfa_reqq_wcancel(__wqe)	list_del(&(__wqe)->qe) - -/* - * Generic BFA callback element. - */ -struct bfa_cb_qe_s { -	struct list_head         qe; -	bfa_cb_cbfn_t  cbfn; -	bfa_boolean_t   once; -	u32		rsvd; -	void           *cbarg; -}; -  #define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\  		(__hcb_qe)->cbfn  = (__cbfn);      \  		(__hcb_qe)->cbarg = (__cbarg);      \ +		(__hcb_qe)->pre_rmv = BFA_FALSE;		\  		list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \  	} while (0) @@ -158,6 +137,11 @@ struct bfa_cb_qe_s {  		}							\  	} while (0) +#define bfa_cb_queue_status(__bfa, __hcb_qe, __status) do {		\ +		(__hcb_qe)->fw_status = (__status);			\ +		list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);	\ +} while (0) +  #define bfa_cb_queue_done(__hcb_qe) do {	\  		(__hcb_qe)->once = BFA_FALSE;	\  	} while (0) @@ -173,44 +157,14 @@ struct bfa_pciid_s {  extern char     bfa_version[]; -/* - * BFA memory resources - */ -enum bfa_mem_type { -	BFA_MEM_TYPE_KVA = 1,	/*  Kernel Virtual Memory *(non-dma-able) */ -	BFA_MEM_TYPE_DMA = 2,	/*  DMA-able memory */ -	BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA, -}; - -struct bfa_mem_elem_s { -	enum bfa_mem_type mem_type;	/* see enum bfa_mem_type */ -	u32	mem_len;	/*  Total Length in Bytes	*/ -	u8		*kva;		/*  kernel virtual address	*/ -	u64	dma;		/*  dma address if DMA memory	*/ -	u8		*kva_curp;	/*  kva allocation cursor	*/ -	u64	dma_curp;	/*  dma allocation cursor	*/ -}; - -struct bfa_meminfo_s { -	struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX]; -}; -#define bfa_meminfo_kva(_m)				\ -	((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp) -#define bfa_meminfo_dma_virt(_m)			\ -	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp) -#define bfa_meminfo_dma_phys(_m)			\ -	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp) -  struct bfa_iocfc_regs_s {  	void __iomem	*intr_status;  	void __iomem	*intr_mask;  	void __iomem	*cpe_q_pi[BFI_IOC_MAX_CQS];  	void __iomem	*cpe_q_ci[BFI_IOC_MAX_CQS]; -	void __iomem	*cpe_q_depth[BFI_IOC_MAX_CQS];  	void __iomem	*cpe_q_ctrl[BFI_IOC_MAX_CQS];  	void __iomem	*rme_q_ci[BFI_IOC_MAX_CQS];  	void __iomem	*rme_q_pi[BFI_IOC_MAX_CQS]; -	void __iomem	*rme_q_depth[BFI_IOC_MAX_CQS];  	void __iomem	*rme_q_ctrl[BFI_IOC_MAX_CQS];  }; @@ -230,35 +184,66 @@ struct bfa_msix_s {  struct bfa_hwif_s {  	void (*hw_reginit)(struct bfa_s *bfa);  	void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq); -	void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq); +	void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq, u32 ci);  	void (*hw_msix_init)(struct bfa_s *bfa, int nvecs); -	void (*hw_msix_install)(struct bfa_s *bfa); +	void (*hw_msix_ctrl_install)(struct bfa_s *bfa); +	void (*hw_msix_queue_install)(struct bfa_s *bfa);  	void (*hw_msix_uninstall)(struct bfa_s *bfa);  	void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);  	void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,  				u32 *nvecs, u32 *maxvec);  	void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,  				       u32 *end); +	int	cpe_vec_q0; +	int	rme_vec_q0;  };  typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status); +struct bfa_faa_cbfn_s { +	bfa_cb_iocfc_t	faa_cbfn; +	void		*faa_cbarg; +}; + +#define BFA_FAA_ENABLED		1 +#define BFA_FAA_DISABLED	2 + +/* + *	FAA attributes + */ +struct bfa_faa_attr_s { +	wwn_t	faa; +	u8	faa_state; +	u8	pwwn_source; +	u8	rsvd[6]; +}; + +struct bfa_faa_args_s { +	struct bfa_faa_attr_s	*faa_attr; +	struct bfa_faa_cbfn_s	faa_cb; +	u8			faa_state; +	bfa_boolean_t		busy; +}; +  struct bfa_iocfc_s { +	bfa_fsm_t		fsm;  	struct bfa_s		*bfa;  	struct bfa_iocfc_cfg_s	cfg; -	int			action;  	u32		req_cq_pi[BFI_IOC_MAX_CQS];  	u32		rsp_cq_ci[BFI_IOC_MAX_CQS]; +	u8		hw_qid[BFI_IOC_MAX_CQS];  	struct bfa_cb_qe_s	init_hcb_qe;  	struct bfa_cb_qe_s	stop_hcb_qe;  	struct bfa_cb_qe_s	dis_hcb_qe; +	struct bfa_cb_qe_s	en_hcb_qe;  	struct bfa_cb_qe_s	stats_hcb_qe; -	bfa_boolean_t		cfgdone; +	bfa_boolean_t		submod_enabled; +	bfa_boolean_t		cb_reqd;	/* Driver call back reqd */ +	bfa_status_t		op_status;	/* Status of bfa iocfc op */  	struct bfa_dma_s	cfg_info;  	struct bfi_iocfc_cfg_s *cfginfo;  	struct bfa_dma_s	cfgrsp_dma;  	struct bfi_iocfc_cfgrsp_s *cfgrsp; -	struct bfi_iocfc_cfg_reply_s *cfg_reply;  	struct bfa_dma_s	req_cq_ba[BFI_IOC_MAX_CQS];  	struct bfa_dma_s	req_cq_shadow_ci[BFI_IOC_MAX_CQS];  	struct bfa_dma_s	rsp_cq_ba[BFI_IOC_MAX_CQS]; @@ -268,18 +253,40 @@ struct bfa_iocfc_s {  	bfa_cb_iocfc_t		updateq_cbfn; /*  bios callback function */  	void			*updateq_cbarg;	/*  bios callback arg */  	u32	intr_mask; +	struct bfa_faa_args_s	faa_args; +	struct bfa_mem_dma_s	ioc_dma; +	struct bfa_mem_dma_s	iocfc_dma; +	struct bfa_mem_dma_s	reqq_dma[BFI_IOC_MAX_CQS]; +	struct bfa_mem_dma_s	rspq_dma[BFI_IOC_MAX_CQS]; +	struct bfa_mem_kva_s	kva_seg;  }; -#define bfa_lpuid(__bfa)						\ -	bfa_ioc_portid(&(__bfa)->ioc) +#define BFA_MEM_IOC_DMA(_bfa)		(&((_bfa)->iocfc.ioc_dma)) +#define BFA_MEM_IOCFC_DMA(_bfa)		(&((_bfa)->iocfc.iocfc_dma)) +#define BFA_MEM_REQQ_DMA(_bfa, _qno)	(&((_bfa)->iocfc.reqq_dma[(_qno)])) +#define BFA_MEM_RSPQ_DMA(_bfa, _qno)	(&((_bfa)->iocfc.rspq_dma[(_qno)])) +#define BFA_MEM_IOCFC_KVA(_bfa)		(&((_bfa)->iocfc.kva_seg)) + +#define bfa_fn_lpu(__bfa)	\ +	bfi_fn_lpu(bfa_ioc_pcifn(&(__bfa)->ioc), bfa_ioc_portid(&(__bfa)->ioc))  #define bfa_msix_init(__bfa, __nvecs)					\  	((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs)) -#define bfa_msix_install(__bfa)						\ -	((__bfa)->iocfc.hwif.hw_msix_install(__bfa)) +#define bfa_msix_ctrl_install(__bfa)					\ +	((__bfa)->iocfc.hwif.hw_msix_ctrl_install(__bfa)) +#define bfa_msix_queue_install(__bfa)					\ +	((__bfa)->iocfc.hwif.hw_msix_queue_install(__bfa))  #define bfa_msix_uninstall(__bfa)					\  	((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa)) -#define bfa_isr_mode_set(__bfa, __msix)					\ -	((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix)) +#define bfa_isr_rspq_ack(__bfa, __queue, __ci)				\ +	((__bfa)->iocfc.hwif.hw_rspq_ack(__bfa, __queue, __ci)) +#define bfa_isr_reqq_ack(__bfa, __queue) do {				\ +	if ((__bfa)->iocfc.hwif.hw_reqq_ack)				\ +		(__bfa)->iocfc.hwif.hw_reqq_ack(__bfa, __queue);	\ +} while (0) +#define bfa_isr_mode_set(__bfa, __msix) do {				\ +	if ((__bfa)->iocfc.hwif.hw_isr_mode_set)			\ +		(__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix);	\ +} while (0)  #define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)		\  	((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap,		\  					__nvecs, __maxvec)) @@ -291,18 +298,17 @@ struct bfa_iocfc_s {  /*   * FC specific IOC functions.   */ -void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -		       u32 *dm_len); +void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, +			struct bfa_meminfo_s *meminfo, +			struct bfa_s *bfa);  void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,  		      struct bfa_iocfc_cfg_s *cfg, -		      struct bfa_meminfo_s *meminfo,  		      struct bfa_pcidev_s *pcidev); -void bfa_iocfc_detach(struct bfa_s *bfa);  void bfa_iocfc_init(struct bfa_s *bfa);  void bfa_iocfc_start(struct bfa_s *bfa);  void bfa_iocfc_stop(struct bfa_s *bfa);  void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg); -void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa); +void bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa);  bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);  void bfa_iocfc_reset_queues(struct bfa_s *bfa); @@ -312,10 +318,10 @@ void bfa_msix_rspq(struct bfa_s *bfa, int vec);  void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);  void bfa_hwcb_reginit(struct bfa_s *bfa); -void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq); -void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq); +void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci);  void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs); -void bfa_hwcb_msix_install(struct bfa_s *bfa); +void bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa); +void bfa_hwcb_msix_queue_install(struct bfa_s *bfa);  void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);  void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);  void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs, @@ -323,22 +329,20 @@ void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,  void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,  				 u32 *end);  void bfa_hwct_reginit(struct bfa_s *bfa); +void bfa_hwct2_reginit(struct bfa_s *bfa);  void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq); -void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq); +void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci); +void bfa_hwct2_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci);  void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs); -void bfa_hwct_msix_install(struct bfa_s *bfa); +void bfa_hwct_msix_ctrl_install(struct bfa_s *bfa); +void bfa_hwct_msix_queue_install(struct bfa_s *bfa);  void bfa_hwct_msix_uninstall(struct bfa_s *bfa);  void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);  void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,  			   u32 *maxvec);  void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start,  				 u32 *end); -void bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi);  void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns); -wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa); -wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa); -void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, -				struct bfa_boot_pbc_s *pbcfg);  int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,  				struct bfi_pbc_vport_s *pbc_vport); @@ -378,27 +382,36 @@ int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,  #define bfa_get_fw_clock_res(__bfa)		\  	((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res) +/* + * lun mask macros return NULL when min cfg is enabled and there is + * no memory allocated for lunmask. + */ +#define bfa_get_lun_mask(__bfa)					\ +	((&(__bfa)->modules.dconf_mod)->min_cfg) ? NULL :	\ +	 (&(BFA_DCONF_MOD(__bfa)->dconf->lun_mask)) + +#define bfa_get_lun_mask_list(_bfa)				\ +	((&(_bfa)->modules.dconf_mod)->min_cfg) ? NULL :	\ +	 (bfa_get_lun_mask(_bfa)->lun_list) + +#define bfa_get_lun_mask_status(_bfa)				\ +	(((&(_bfa)->modules.dconf_mod)->min_cfg)		\ +	 ? BFA_LUNMASK_MINCFG : ((bfa_get_lun_mask(_bfa))->status)) +  void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);  void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);  void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);  void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, -			 struct bfa_meminfo_s *meminfo); +			struct bfa_meminfo_s *meminfo, +			struct bfa_s *bfa);  void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  		struct bfa_meminfo_s *meminfo,  		struct bfa_pcidev_s *pcidev); -void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod); -void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);  void bfa_detach(struct bfa_s *bfa); -void bfa_init(struct bfa_s *bfa); -void bfa_start(struct bfa_s *bfa); -void bfa_stop(struct bfa_s *bfa); -void bfa_attach_fcs(struct bfa_s *bfa);  void bfa_cb_init(void *bfad, bfa_status_t status);  void bfa_cb_updateq(void *bfad, bfa_status_t status);  bfa_boolean_t bfa_intx(struct bfa_s *bfa); -void bfa_intx_disable(struct bfa_s *bfa); -void bfa_intx_enable(struct bfa_s *bfa);  void bfa_isr_enable(struct bfa_s *bfa);  void bfa_isr_disable(struct bfa_s *bfa); @@ -408,31 +421,28 @@ void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);  typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);  void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr); -void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr); -void bfa_adapter_get_attr(struct bfa_s *bfa, -			  struct bfa_adapter_attr_s *ad_attr); -u64 bfa_adapter_get_id(struct bfa_s *bfa);  bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,  				   struct bfa_iocfc_intr_attr_s *attr);  void bfa_iocfc_enable(struct bfa_s *bfa);  void bfa_iocfc_disable(struct bfa_s *bfa); -void bfa_chip_reset(struct bfa_s *bfa); -void bfa_timer_tick(struct bfa_s *bfa);  #define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)		\  	bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout) -/* - * BFA debug API functions - */ -bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen); -bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen); -bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf, -			      u32 *offset, int *buflen); -void bfa_debug_fwsave_clear(struct bfa_s *bfa); -bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data); -bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa); +struct bfa_cb_pending_q_s { +	struct bfa_cb_qe_s	hcb_qe; +	void			*data;  /* Driver buffer */ +}; + +/* Common macros to operate on pending stats/attr apis */ +#define bfa_pending_q_init(__qe, __cbfn, __cbarg, __data) do {	\ +	bfa_q_qe_init(&((__qe)->hcb_qe.qe));			\ +	(__qe)->hcb_qe.cbfn = (__cbfn);				\ +	(__qe)->hcb_qe.cbarg = (__cbarg);			\ +	(__qe)->hcb_qe.pre_rmv = BFA_TRUE;			\ +	(__qe)->data = (__data);				\ +} while (0)  #endif /* __BFA_H__ */ diff --git a/drivers/scsi/bfa/bfa_cb_ioim.h b/drivers/scsi/bfa/bfa_cb_ioim.h deleted file mode 100644 index 6f021015f1f..00000000000 --- a/drivers/scsi/bfa/bfa_cb_ioim.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. - * All rights reserved - * www.brocade.com - * - * Linux driver for Brocade Fibre Channel Host Bus Adapter. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License (GPL) Version 2 as - * published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - */ - -#ifndef __BFA_HCB_IOIM_H__ -#define __BFA_HCB_IOIM_H__ - -#include "bfa_os_inc.h" -/* - * task attribute values in FCP-2 FCP_CMND IU - */ -#define SIMPLE_Q    0 -#define HEAD_OF_Q   1 -#define ORDERED_Q   2 -#define ACA_Q	    4 -#define UNTAGGED    5 - -static inline lun_t -bfad_int_to_lun(u32 luno) -{ -	union { -		u16	scsi_lun[4]; -		lun_t		bfa_lun; -	} lun; - -	lun.bfa_lun     = 0; -	lun.scsi_lun[0] = cpu_to_be16(luno); - -	return lun.bfa_lun; -} - -/* - * Get LUN for the I/O request - */ -#define bfa_cb_ioim_get_lun(__dio)	\ -	bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun) - -/* - * Get CDB for the I/O request - */ -static inline u8 * -bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio) -{ -	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - -	return (u8 *) cmnd->cmnd; -} - -/* - * Get I/O direction (read/write) for the I/O request - */ -static inline enum fcp_iodir -bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio) -{ -	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; -	enum dma_data_direction dmadir; - -	dmadir = cmnd->sc_data_direction; -	if (dmadir == DMA_TO_DEVICE) -		return FCP_IODIR_WRITE; -	else if (dmadir == DMA_FROM_DEVICE) -		return FCP_IODIR_READ; -	else -		return FCP_IODIR_NONE; -} - -/* - * Get IO size in bytes for the I/O request - */ -static inline u32 -bfa_cb_ioim_get_size(struct bfad_ioim_s *dio) -{ -	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - -	return scsi_bufflen(cmnd); -} - -/* - * Get timeout for the I/O request - */ -static inline u8 -bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio) -{ -	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; -	/* -	 * TBD: need a timeout for scsi passthru -	 */ -	if (cmnd->device->host == NULL) -		return 4; - -	return 0; -} - -/* - * Get Command Reference Number for the I/O request. 0 if none. - */ -static inline u8 -bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio) -{ -	return 0; -} - -/* - * Get SAM-3 priority for the I/O request. 0 is default. - */ -static inline u8 -bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio) -{ -	return 0; -} - -/* - * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0). - */ -static inline u8 -bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio) -{ -	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; -	u8	task_attr = UNTAGGED; - -	if (cmnd->device->tagged_supported) { -		switch (cmnd->tag) { -		case HEAD_OF_QUEUE_TAG: -			task_attr = HEAD_OF_Q; -			break; -		case ORDERED_QUEUE_TAG: -			task_attr = ORDERED_Q; -			break; -		default: -			task_attr = SIMPLE_Q; -			break; -		} -	} - -	return task_attr; -} - -/* - * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16). - */ -static inline u8 -bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio) -{ -	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - -	return cmnd->cmd_len; -} - -/* - * Assign queue to be used for the I/O request. This value depends on whether - * the driver wants to use the queues via any specific algorithm. Currently, - * this is not supported. - */ -#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE - -#endif /* __BFA_HCB_IOIM_H__ */ diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 2345f48dc57..e3f67b097a5 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -15,13 +15,167 @@   * General Public License for more details.   */ -#include "bfa_modules.h" -#include "bfi_ctreg.h"  #include "bfad_drv.h" +#include "bfa_modules.h" +#include "bfi_reg.h"  BFA_TRC_FILE(HAL, CORE);  /* + * BFA module list terminated by NULL + */ +static struct bfa_module_s *hal_mods[] = { +	&hal_mod_fcdiag, +	&hal_mod_sgpg, +	&hal_mod_fcport, +	&hal_mod_fcxp, +	&hal_mod_lps, +	&hal_mod_uf, +	&hal_mod_rport, +	&hal_mod_fcp, +	&hal_mod_dconf, +	NULL +}; + +/* + * Message handlers for various modules. + */ +static bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = { +	bfa_isr_unhandled,	/* NONE */ +	bfa_isr_unhandled,	/* BFI_MC_IOC */ +	bfa_fcdiag_intr,	/* BFI_MC_DIAG */ +	bfa_isr_unhandled,	/* BFI_MC_FLASH */ +	bfa_isr_unhandled,	/* BFI_MC_CEE */ +	bfa_fcport_isr,		/* BFI_MC_FCPORT */ +	bfa_isr_unhandled,	/* BFI_MC_IOCFC */ +	bfa_isr_unhandled,	/* BFI_MC_LL */ +	bfa_uf_isr,		/* BFI_MC_UF */ +	bfa_fcxp_isr,		/* BFI_MC_FCXP */ +	bfa_lps_isr,		/* BFI_MC_LPS */ +	bfa_rport_isr,		/* BFI_MC_RPORT */ +	bfa_itn_isr,		/* BFI_MC_ITN */ +	bfa_isr_unhandled,	/* BFI_MC_IOIM_READ */ +	bfa_isr_unhandled,	/* BFI_MC_IOIM_WRITE */ +	bfa_isr_unhandled,	/* BFI_MC_IOIM_IO */ +	bfa_ioim_isr,		/* BFI_MC_IOIM */ +	bfa_ioim_good_comp_isr,	/* BFI_MC_IOIM_IOCOM */ +	bfa_tskim_isr,		/* BFI_MC_TSKIM */ +	bfa_isr_unhandled,	/* BFI_MC_SBOOT */ +	bfa_isr_unhandled,	/* BFI_MC_IPFC */ +	bfa_isr_unhandled,	/* BFI_MC_PORT */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +	bfa_isr_unhandled,	/* --------- */ +}; +/* + * Message handlers for mailbox command classes + */ +static bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = { +	NULL, +	NULL,		/* BFI_MC_IOC   */ +	NULL,		/* BFI_MC_DIAG  */ +	NULL,		/* BFI_MC_FLASH */ +	NULL,		/* BFI_MC_CEE   */ +	NULL,		/* BFI_MC_PORT  */ +	bfa_iocfc_isr,	/* BFI_MC_IOCFC */ +	NULL, +}; + + + +static void +bfa_com_port_attach(struct bfa_s *bfa) +{ +	struct bfa_port_s	*port = &bfa->modules.port; +	struct bfa_mem_dma_s	*port_dma = BFA_MEM_PORT_DMA(bfa); + +	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod); +	bfa_port_mem_claim(port, port_dma->kva_curp, port_dma->dma_curp); +} + +/* + * ablk module attach + */ +static void +bfa_com_ablk_attach(struct bfa_s *bfa) +{ +	struct bfa_ablk_s	*ablk = &bfa->modules.ablk; +	struct bfa_mem_dma_s	*ablk_dma = BFA_MEM_ABLK_DMA(bfa); + +	bfa_ablk_attach(ablk, &bfa->ioc); +	bfa_ablk_memclaim(ablk, ablk_dma->kva_curp, ablk_dma->dma_curp); +} + +static void +bfa_com_cee_attach(struct bfa_s *bfa) +{ +	struct bfa_cee_s	*cee = &bfa->modules.cee; +	struct bfa_mem_dma_s	*cee_dma = BFA_MEM_CEE_DMA(bfa); + +	cee->trcmod = bfa->trcmod; +	bfa_cee_attach(cee, &bfa->ioc, bfa); +	bfa_cee_mem_claim(cee, cee_dma->kva_curp, cee_dma->dma_curp); +} + +static void +bfa_com_sfp_attach(struct bfa_s *bfa) +{ +	struct bfa_sfp_s	*sfp = BFA_SFP_MOD(bfa); +	struct bfa_mem_dma_s	*sfp_dma = BFA_MEM_SFP_DMA(bfa); + +	bfa_sfp_attach(sfp, &bfa->ioc, bfa, bfa->trcmod); +	bfa_sfp_memclaim(sfp, sfp_dma->kva_curp, sfp_dma->dma_curp); +} + +static void +bfa_com_flash_attach(struct bfa_s *bfa, bfa_boolean_t mincfg) +{ +	struct bfa_flash_s	*flash = BFA_FLASH(bfa); +	struct bfa_mem_dma_s	*flash_dma = BFA_MEM_FLASH_DMA(bfa); + +	bfa_flash_attach(flash, &bfa->ioc, bfa, bfa->trcmod, mincfg); +	bfa_flash_memclaim(flash, flash_dma->kva_curp, +			   flash_dma->dma_curp, mincfg); +} + +static void +bfa_com_diag_attach(struct bfa_s *bfa) +{ +	struct bfa_diag_s	*diag = BFA_DIAG_MOD(bfa); +	struct bfa_mem_dma_s	*diag_dma = BFA_MEM_DIAG_DMA(bfa); + +	bfa_diag_attach(diag, &bfa->ioc, bfa, bfa_fcport_beacon, bfa->trcmod); +	bfa_diag_memclaim(diag, diag_dma->kva_curp, diag_dma->dma_curp); +} + +static void +bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg) +{ +	struct bfa_phy_s	*phy = BFA_PHY(bfa); +	struct bfa_mem_dma_s	*phy_dma = BFA_MEM_PHY_DMA(bfa); + +	bfa_phy_attach(phy, &bfa->ioc, bfa, bfa->trcmod, mincfg); +	bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg); +} + +static void +bfa_com_fru_attach(struct bfa_s *bfa, bfa_boolean_t mincfg) +{ +	struct bfa_fru_s	*fru = BFA_FRU(bfa); +	struct bfa_mem_dma_s	*fru_dma = BFA_MEM_FRU_DMA(bfa); + +	bfa_fru_attach(fru, &bfa->ioc, bfa, bfa->trcmod, mincfg); +	bfa_fru_memclaim(fru, fru_dma->kva_curp, fru_dma->dma_curp, mincfg); +} + +/*   * BFA IOC FC related definitions   */ @@ -35,6 +189,7 @@ enum {  	BFA_IOCFC_ACT_INIT	= 1,  	BFA_IOCFC_ACT_STOP	= 2,  	BFA_IOCFC_ACT_DISABLE	= 3, +	BFA_IOCFC_ACT_ENABLE	= 4,  };  #define DEF_CFG_NUM_FABRICS		1 @@ -55,30 +210,489 @@ enum {  #define DEF_CFG_NUM_SBOOT_LUNS		16  /* + * IOCFC state machine definitions/declarations + */ +bfa_fsm_state_decl(bfa_iocfc, stopped, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, initing, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, dconf_read, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, init_cfg_wait, +		   struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, init_cfg_done, +		   struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, operational, +		   struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, dconf_write, +		   struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, stopping, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, enabling, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, cfg_wait, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, disabling, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, disabled, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, failed, struct bfa_iocfc_s, enum iocfc_event); +bfa_fsm_state_decl(bfa_iocfc, init_failed, +		   struct bfa_iocfc_s, enum iocfc_event); + +/*   * forward declaration for IOC FC functions   */ +static void bfa_iocfc_start_submod(struct bfa_s *bfa); +static void bfa_iocfc_disable_submod(struct bfa_s *bfa); +static void bfa_iocfc_send_cfg(void *bfa_arg);  static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);  static void bfa_iocfc_disable_cbfn(void *bfa_arg);  static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);  static void bfa_iocfc_reset_cbfn(void *bfa_arg);  static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn; +static void bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete); +static void bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl); +static void bfa_iocfc_enable_cb(void *bfa_arg, bfa_boolean_t compl); +static void bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl); + +static void +bfa_iocfc_sm_stopped_entry(struct bfa_iocfc_s *iocfc) +{ +} -/* - * BFA Interrupt handling functions - */  static void -bfa_msix_errint(struct bfa_s *bfa, u32 intr) +bfa_iocfc_sm_stopped(struct bfa_iocfc_s *iocfc, enum iocfc_event event)  { -	bfa_ioc_error_isr(&bfa->ioc); +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_INIT: +	case IOCFC_E_ENABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_initing); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	}  }  static void -bfa_msix_lpu(struct bfa_s *bfa) +bfa_iocfc_sm_initing_entry(struct bfa_iocfc_s *iocfc)  { -	bfa_ioc_mbox_isr(&bfa->ioc); +	bfa_ioc_enable(&iocfc->bfa->ioc); +} + +static void +bfa_iocfc_sm_initing(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_IOC_ENABLED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_read); +		break; + +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; + +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping); +		break; + +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	}  }  static void +bfa_iocfc_sm_dconf_read_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_dconf_modinit(iocfc->bfa); +} + +static void +bfa_iocfc_sm_dconf_read(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_DCONF_DONE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_cfg_wait); +		break; + +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; + +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping); +		break; + +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_init_cfg_wait_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_iocfc_send_cfg(iocfc->bfa); +} + +static void +bfa_iocfc_sm_init_cfg_wait(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_CFG_DONE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_cfg_done); +		break; + +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; + +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping); +		break; + +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_init_failed); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_init_cfg_done_entry(struct bfa_iocfc_s *iocfc) +{ +	iocfc->bfa->iocfc.op_status = BFA_STATUS_OK; +	bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.init_hcb_qe, +		     bfa_iocfc_init_cb, iocfc->bfa); +} + +static void +bfa_iocfc_sm_init_cfg_done(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_START: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_operational); +		break; +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping); +		break; +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_operational_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_fcport_init(iocfc->bfa); +	bfa_iocfc_start_submod(iocfc->bfa); +} + +static void +bfa_iocfc_sm_operational(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write); +		break; +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_dconf_write_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_dconf_modexit(iocfc->bfa); +} + +static void +bfa_iocfc_sm_dconf_write(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_DCONF_DONE: +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_stopping_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_ioc_disable(&iocfc->bfa->ioc); +} + +static void +bfa_iocfc_sm_stopping(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_IOC_DISABLED: +		bfa_isr_disable(iocfc->bfa); +		bfa_iocfc_disable_submod(iocfc->bfa); +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopped); +		iocfc->bfa->iocfc.op_status = BFA_STATUS_OK; +		bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.stop_hcb_qe, +			     bfa_iocfc_stop_cb, iocfc->bfa); +		break; + +	case IOCFC_E_IOC_ENABLED: +	case IOCFC_E_DCONF_DONE: +	case IOCFC_E_CFG_DONE: +		break; + +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_enabling_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_ioc_enable(&iocfc->bfa->ioc); +} + +static void +bfa_iocfc_sm_enabling(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_IOC_ENABLED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_cfg_wait); +		break; + +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; + +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write); +		break; + +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed); + +		if (iocfc->bfa->iocfc.cb_reqd == BFA_FALSE) +			break; + +		iocfc->bfa->iocfc.op_status = BFA_STATUS_FAILED; +		bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.en_hcb_qe, +			     bfa_iocfc_enable_cb, iocfc->bfa); +		iocfc->bfa->iocfc.cb_reqd = BFA_FALSE; +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_cfg_wait_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_iocfc_send_cfg(iocfc->bfa); +} + +static void +bfa_iocfc_sm_cfg_wait(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_CFG_DONE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_operational); +		if (iocfc->bfa->iocfc.cb_reqd == BFA_FALSE) +			break; + +		iocfc->bfa->iocfc.op_status = BFA_STATUS_OK; +		bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.en_hcb_qe, +			     bfa_iocfc_enable_cb, iocfc->bfa); +		iocfc->bfa->iocfc.cb_reqd = BFA_FALSE; +		break; +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; + +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write); +		break; +	case IOCFC_E_IOC_FAILED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_failed); +		if (iocfc->bfa->iocfc.cb_reqd == BFA_FALSE) +			break; + +		iocfc->bfa->iocfc.op_status = BFA_STATUS_FAILED; +		bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.en_hcb_qe, +			     bfa_iocfc_enable_cb, iocfc->bfa); +		iocfc->bfa->iocfc.cb_reqd = BFA_FALSE; +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_disabling_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_ioc_disable(&iocfc->bfa->ioc); +} + +static void +bfa_iocfc_sm_disabling(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_IOC_DISABLED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabled); +		break; +	case IOCFC_E_IOC_ENABLED: +	case IOCFC_E_DCONF_DONE: +	case IOCFC_E_CFG_DONE: +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_disabled_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_isr_disable(iocfc->bfa); +	bfa_iocfc_disable_submod(iocfc->bfa); +	iocfc->bfa->iocfc.op_status = BFA_STATUS_OK; +	bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.dis_hcb_qe, +		     bfa_iocfc_disable_cb, iocfc->bfa); +} + +static void +bfa_iocfc_sm_disabled(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write); +		break; +	case IOCFC_E_ENABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_enabling); +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_failed_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_isr_disable(iocfc->bfa); +	bfa_iocfc_disable_submod(iocfc->bfa); +} + +static void +bfa_iocfc_sm_failed(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_write); +		break; +	case IOCFC_E_DISABLE: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_disabling); +		break; +	case IOCFC_E_IOC_ENABLED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_cfg_wait); +		break; +	case IOCFC_E_IOC_FAILED: +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +static void +bfa_iocfc_sm_init_failed_entry(struct bfa_iocfc_s *iocfc) +{ +	bfa_isr_disable(iocfc->bfa); +	iocfc->bfa->iocfc.op_status = BFA_STATUS_FAILED; +	bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.init_hcb_qe, +		     bfa_iocfc_init_cb, iocfc->bfa); +} + +static void +bfa_iocfc_sm_init_failed(struct bfa_iocfc_s *iocfc, enum iocfc_event event) +{ +	bfa_trc(iocfc->bfa, event); + +	switch (event) { +	case IOCFC_E_STOP: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopping); +		break; +	case IOCFC_E_DISABLE: +		bfa_ioc_disable(&iocfc->bfa->ioc); +		break; +	case IOCFC_E_IOC_ENABLED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_dconf_read); +		break; +	case IOCFC_E_IOC_DISABLED: +		bfa_fsm_set_state(iocfc, bfa_iocfc_sm_stopped); +		iocfc->bfa->iocfc.op_status = BFA_STATUS_OK; +		bfa_cb_queue(iocfc->bfa, &iocfc->bfa->iocfc.dis_hcb_qe, +			     bfa_iocfc_disable_cb, iocfc->bfa); +		break; +	case IOCFC_E_IOC_FAILED: +		break; +	default: +		bfa_sm_fault(iocfc->bfa, event); +		break; +	} +} + +/* + * BFA Interrupt handling functions + */ +static void  bfa_reqq_resume(struct bfa_s *bfa, int qid)  {  	struct list_head *waitq, *qe, *qen; @@ -98,125 +712,182 @@ bfa_reqq_resume(struct bfa_s *bfa, int qid)  	}  } -void -bfa_msix_all(struct bfa_s *bfa, int vec) +bfa_boolean_t +bfa_isr_rspq(struct bfa_s *bfa, int qid)  { -	bfa_intx(bfa); +	struct bfi_msg_s *m; +	u32	pi, ci; +	struct list_head *waitq; +	bfa_boolean_t ret; + +	ci = bfa_rspq_ci(bfa, qid); +	pi = bfa_rspq_pi(bfa, qid); + +	ret = (ci != pi); + +	while (ci != pi) { +		m = bfa_rspq_elem(bfa, qid, ci); +		WARN_ON(m->mhdr.msg_class >= BFI_MC_MAX); + +		bfa_isrs[m->mhdr.msg_class] (bfa, m); +		CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems); +	} + +	/* +	 * acknowledge RME completions and update CI +	 */ +	bfa_isr_rspq_ack(bfa, qid, ci); + +	/* +	 * Resume any pending requests in the corresponding reqq. +	 */ +	waitq = bfa_reqq(bfa, qid); +	if (!list_empty(waitq)) +		bfa_reqq_resume(bfa, qid); + +	return ret;  } -/* - *  hal_intr_api - */ -bfa_boolean_t -bfa_intx(struct bfa_s *bfa) +static inline void +bfa_isr_reqq(struct bfa_s *bfa, int qid)  { -	u32 intr, qintr; -	int queue; +	struct list_head *waitq; + +	bfa_isr_reqq_ack(bfa, qid); + +	/* +	 * Resume any pending requests in the corresponding reqq. +	 */ +	waitq = bfa_reqq(bfa, qid); +	if (!list_empty(waitq)) +		bfa_reqq_resume(bfa, qid); +} + +void +bfa_msix_all(struct bfa_s *bfa, int vec) +{ +	u32	intr, qintr; +	int	queue;  	intr = readl(bfa->iocfc.bfa_regs.intr_status);  	if (!intr) -		return BFA_FALSE; +		return;  	/*  	 * RME completion queue interrupt  	 */  	qintr = intr & __HFN_INT_RME_MASK; -	writel(qintr, bfa->iocfc.bfa_regs.intr_status); - -	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) { -		if (intr & (__HFN_INT_RME_Q0 << queue)) -			bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1)); +	if (qintr && bfa->queue_process) { +		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++) +			bfa_isr_rspq(bfa, queue);  	} +  	intr &= ~qintr;  	if (!intr) -		return BFA_TRUE; +		return;  	/*  	 * CPE completion queue interrupt  	 */  	qintr = intr & __HFN_INT_CPE_MASK; -	writel(qintr, bfa->iocfc.bfa_regs.intr_status); - -	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) { -		if (intr & (__HFN_INT_CPE_Q0 << queue)) -			bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1)); +	if (qintr && bfa->queue_process) { +		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++) +			bfa_isr_reqq(bfa, queue);  	}  	intr &= ~qintr;  	if (!intr) -		return BFA_TRUE; +		return;  	bfa_msix_lpu_err(bfa, intr); - -	return BFA_TRUE;  } -void -bfa_intx_enable(struct bfa_s *bfa) +bfa_boolean_t +bfa_intx(struct bfa_s *bfa)  { -	writel(bfa->iocfc.intr_mask, bfa->iocfc.bfa_regs.intr_mask); -} +	u32 intr, qintr; +	int queue; +	bfa_boolean_t rspq_comp = BFA_FALSE; -void -bfa_intx_disable(struct bfa_s *bfa) -{ -	writel(-1L, bfa->iocfc.bfa_regs.intr_mask); +	intr = readl(bfa->iocfc.bfa_regs.intr_status); + +	qintr = intr & (__HFN_INT_RME_MASK | __HFN_INT_CPE_MASK); +	if (qintr) +		writel(qintr, bfa->iocfc.bfa_regs.intr_status); + +	/* +	 * Unconditional RME completion queue interrupt +	 */ +	if (bfa->queue_process) { +		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++) +			if (bfa_isr_rspq(bfa, queue)) +				rspq_comp = BFA_TRUE; +	} + +	if (!intr) +		return (qintr | rspq_comp) ? BFA_TRUE : BFA_FALSE; + +	/* +	 * CPE completion queue interrupt +	 */ +	qintr = intr & __HFN_INT_CPE_MASK; +	if (qintr && bfa->queue_process) { +		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++) +			bfa_isr_reqq(bfa, queue); +	} +	intr &= ~qintr; +	if (!intr) +		return BFA_TRUE; + +	if (bfa->intr_enabled) +		bfa_msix_lpu_err(bfa, intr); + +	return BFA_TRUE;  }  void  bfa_isr_enable(struct bfa_s *bfa)  { -	u32 intr_unmask; -	int pci_func = bfa_ioc_pcifn(&bfa->ioc); +	u32 umsk; +	int port_id = bfa_ioc_portid(&bfa->ioc); -	bfa_trc(bfa, pci_func); +	bfa_trc(bfa, bfa_ioc_pcifn(&bfa->ioc)); +	bfa_trc(bfa, port_id); -	bfa_msix_install(bfa); -	intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | -		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | -		       __HFN_INT_LL_HALT); +	bfa_msix_ctrl_install(bfa); -	if (pci_func == 0) -		intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | -				__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 | -				__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | -				__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | -				__HFN_INT_MBOX_LPU0); -	else -		intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | -				__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 | -				__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | -				__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | -				__HFN_INT_MBOX_LPU1); - -	writel(intr_unmask, bfa->iocfc.bfa_regs.intr_status); -	writel(~intr_unmask, bfa->iocfc.bfa_regs.intr_mask); -	bfa->iocfc.intr_mask = ~intr_unmask; +	if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) { +		umsk = __HFN_INT_ERR_MASK_CT2; +		umsk |= port_id == 0 ? +			__HFN_INT_FN0_MASK_CT2 : __HFN_INT_FN1_MASK_CT2; +	} else { +		umsk = __HFN_INT_ERR_MASK; +		umsk |= port_id == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK; +	} + +	writel(umsk, bfa->iocfc.bfa_regs.intr_status); +	writel(~umsk, bfa->iocfc.bfa_regs.intr_mask); +	bfa->iocfc.intr_mask = ~umsk;  	bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0); + +	/* +	 * Set the flag indicating successful enabling of interrupts +	 */ +	bfa->intr_enabled = BFA_TRUE;  }  void  bfa_isr_disable(struct bfa_s *bfa)  { +	bfa->intr_enabled = BFA_FALSE;  	bfa_isr_mode_set(bfa, BFA_FALSE);  	writel(-1L, bfa->iocfc.bfa_regs.intr_mask);  	bfa_msix_uninstall(bfa);  }  void -bfa_msix_reqq(struct bfa_s *bfa, int qid) +bfa_msix_reqq(struct bfa_s *bfa, int vec)  { -	struct list_head *waitq; - -	qid &= (BFI_IOC_MAX_CQS - 1); - -	bfa->iocfc.hwif.hw_reqq_ack(bfa, qid); - -	/* -	 * Resume any pending requests in the corresponding reqq. -	 */ -	waitq = bfa_reqq(bfa, qid); -	if (!list_empty(waitq)) -		bfa_reqq_resume(bfa, qid); +	bfa_isr_reqq(bfa, vec - bfa->iocfc.hwif.cpe_vec_q0);  }  void @@ -225,70 +896,43 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)  	bfa_trc(bfa, m->mhdr.msg_class);  	bfa_trc(bfa, m->mhdr.msg_id);  	bfa_trc(bfa, m->mhdr.mtag.i2htok); -	bfa_assert(0); +	WARN_ON(1);  	bfa_trc_stop(bfa->trcmod);  }  void -bfa_msix_rspq(struct bfa_s *bfa, int qid) +bfa_msix_rspq(struct bfa_s *bfa, int vec)  { -	struct bfi_msg_s *m; -	u32 pi, ci; -	struct list_head *waitq; - -	bfa_trc_fp(bfa, qid); - -	qid &= (BFI_IOC_MAX_CQS - 1); - -	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid); - -	ci = bfa_rspq_ci(bfa, qid); -	pi = bfa_rspq_pi(bfa, qid); - -	bfa_trc_fp(bfa, ci); -	bfa_trc_fp(bfa, pi); - -	if (bfa->rme_process) { -		while (ci != pi) { -			m = bfa_rspq_elem(bfa, qid, ci); -			bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX); - -			bfa_isrs[m->mhdr.msg_class] (bfa, m); - -			CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems); -		} -	} - -	/* -	 * update CI -	 */ -	bfa_rspq_ci(bfa, qid) = pi; -	writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]); -	mmiowb(); - -	/* -	 * Resume any pending requests in the corresponding reqq. -	 */ -	waitq = bfa_reqq(bfa, qid); -	if (!list_empty(waitq)) -		bfa_reqq_resume(bfa, qid); +	bfa_isr_rspq(bfa, vec - bfa->iocfc.hwif.rme_vec_q0);  }  void  bfa_msix_lpu_err(struct bfa_s *bfa, int vec)  {  	u32 intr, curr_value; +	bfa_boolean_t lpu_isr, halt_isr, pss_isr;  	intr = readl(bfa->iocfc.bfa_regs.intr_status); -	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1)) -		bfa_msix_lpu(bfa); +	if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) { +		halt_isr = intr & __HFN_INT_CPQ_HALT_CT2; +		pss_isr  = intr & __HFN_INT_ERR_PSS_CT2; +		lpu_isr  = intr & (__HFN_INT_MBOX_LPU0_CT2 | +				   __HFN_INT_MBOX_LPU1_CT2); +		intr    &= __HFN_INT_ERR_MASK_CT2; +	} else { +		halt_isr = bfa_asic_id_ct(bfa->ioc.pcidev.device_id) ? +					  (intr & __HFN_INT_LL_HALT) : 0; +		pss_isr  = intr & __HFN_INT_ERR_PSS; +		lpu_isr  = intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1); +		intr    &= __HFN_INT_ERR_MASK; +	} -	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | -		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT); +	if (lpu_isr) +		bfa_ioc_mbox_isr(&bfa->ioc);  	if (intr) { -		if (intr & __HFN_INT_LL_HALT) { +		if (halt_isr) {  			/*  			 * If LL_HALT bit is set then FW Init Halt LL Port  			 * Register needs to be cleared as well so Interrupt @@ -299,73 +943,31 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)  			writel(curr_value, bfa->ioc.ioc_regs.ll_halt);  		} -		if (intr & __HFN_INT_ERR_PSS) { +		if (pss_isr) {  			/*  			 * ERR_PSS bit needs to be cleared as well in case  			 * interrups are shared so driver's interrupt handler is -			 * still called eventhough it is already masked out. +			 * still called even though it is already masked out.  			 */  			curr_value = readl(  					bfa->ioc.ioc_regs.pss_err_status_reg); -			curr_value &= __PSS_ERR_STATUS_SET;  			writel(curr_value,  				bfa->ioc.ioc_regs.pss_err_status_reg);  		}  		writel(intr, bfa->iocfc.bfa_regs.intr_status); -		bfa_msix_errint(bfa, intr); +		bfa_ioc_error_isr(&bfa->ioc);  	}  } -void -bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func) -{ -	bfa_isrs[mc] = isr_func; -} -  /*   * BFA IOC FC related functions   */  /* - *  hal_ioc_pvt BFA IOC private functions + *  BFA IOC private functions   */ -static void -bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len) -{ -	int		i, per_reqq_sz, per_rspq_sz; - -	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ), -				  BFA_DMA_ALIGN_SZ); -	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ), -				  BFA_DMA_ALIGN_SZ); - -	/* -	 * Calculate CQ size -	 */ -	for (i = 0; i < cfg->fwcfg.num_cqs; i++) { -		*dm_len = *dm_len + per_reqq_sz; -		*dm_len = *dm_len + per_rspq_sz; -	} - -	/* -	 * Calculate Shadow CI/PI size -	 */ -	for (i = 0; i < cfg->fwcfg.num_cqs; i++) -		*dm_len += (2 * BFA_CACHELINE_SZ); -} - -static void -bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len) -{ -	*dm_len += -		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); -	*dm_len += -		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), -			    BFA_CACHELINE_SZ); -} -  /*   * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ   */ @@ -379,7 +981,7 @@ bfa_iocfc_send_cfg(void *bfa_arg)  	struct bfa_iocfc_cfg_s	*cfg = &iocfc->cfg;  	int		i; -	bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS); +	WARN_ON(cfg->fwcfg.num_cqs > BFI_IOC_MAX_CQS);  	bfa_trc(bfa, cfg->fwcfg.num_cqs);  	bfa_iocfc_reset_queues(bfa); @@ -387,8 +989,14 @@ bfa_iocfc_send_cfg(void *bfa_arg)  	/*  	 * initialize IOC configuration info  	 */ +	cfg_info->single_msix_vec = 0; +	if (bfa->msix.nvecs == 1) +		cfg_info->single_msix_vec = 1;  	cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;  	cfg_info->num_cqs = cfg->fwcfg.num_cqs; +	cfg_info->num_ioim_reqs = cpu_to_be16(bfa_fcpim_get_throttle_cfg(bfa, +					       cfg->fwcfg.num_ioim_reqs)); +	cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);  	bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);  	/* @@ -414,16 +1022,14 @@ bfa_iocfc_send_cfg(void *bfa_arg)  	 * Enable interrupt coalescing if it is driver init path  	 * and not ioc disable/enable path.  	 */ -	if (!iocfc->cfgdone) +	if (bfa_fsm_cmp_state(iocfc, bfa_iocfc_sm_init_cfg_wait))  		cfg_info->intr_attr.coalesce = BFA_TRUE; -	iocfc->cfgdone = BFA_FALSE; -  	/*  	 * dma map IOC configuration itself  	 */  	bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ, -		    bfa_lpuid(bfa)); +		    bfa_fn_lpu(bfa));  	bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);  	bfa_ioc_mbox_send(&bfa->ioc, &cfg_req, @@ -438,33 +1044,45 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	bfa->bfad = bfad;  	iocfc->bfa = bfa; -	iocfc->action = BFA_IOCFC_ACT_NONE; -  	iocfc->cfg = *cfg;  	/*  	 * Initialize chip specific handlers.  	 */ -	if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) { +	if (bfa_asic_id_ctc(bfa_ioc_devid(&bfa->ioc))) {  		iocfc->hwif.hw_reginit = bfa_hwct_reginit;  		iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;  		iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;  		iocfc->hwif.hw_msix_init = bfa_hwct_msix_init; -		iocfc->hwif.hw_msix_install = bfa_hwct_msix_install; +		iocfc->hwif.hw_msix_ctrl_install = bfa_hwct_msix_ctrl_install; +		iocfc->hwif.hw_msix_queue_install = bfa_hwct_msix_queue_install;  		iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;  		iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;  		iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;  		iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range; +		iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CT; +		iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CT;  	} else {  		iocfc->hwif.hw_reginit = bfa_hwcb_reginit; -		iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack; +		iocfc->hwif.hw_reqq_ack = NULL;  		iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;  		iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init; -		iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install; +		iocfc->hwif.hw_msix_ctrl_install = bfa_hwcb_msix_ctrl_install; +		iocfc->hwif.hw_msix_queue_install = bfa_hwcb_msix_queue_install;  		iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;  		iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;  		iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;  		iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range; +		iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CB + +			bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS; +		iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CB + +			bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS; +	} + +	if (bfa_asic_id_ct2(bfa_ioc_devid(&bfa->ioc))) { +		iocfc->hwif.hw_reginit = bfa_hwct2_reginit; +		iocfc->hwif.hw_isr_mode_set = NULL; +		iocfc->hwif.hw_rspq_ack = bfa_hwct2_rspq_ack;  	}  	iocfc->hwif.hw_reginit(bfa); @@ -472,48 +1090,42 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  }  static void -bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg, -		    struct bfa_meminfo_s *meminfo) +bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)  { -	u8	       *dm_kva; -	u64	dm_pa; -	int		i, per_reqq_sz, per_rspq_sz; +	u8	*dm_kva = NULL; +	u64	dm_pa = 0; +	int	i, per_reqq_sz, per_rspq_sz;  	struct bfa_iocfc_s  *iocfc = &bfa->iocfc; -	int		dbgsz; +	struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa); +	struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa); +	struct bfa_mem_dma_s *reqq_dma, *rspq_dma; -	dm_kva = bfa_meminfo_dma_virt(meminfo); -	dm_pa = bfa_meminfo_dma_phys(meminfo); +	/* First allocate dma memory for IOC */ +	bfa_ioc_mem_claim(&bfa->ioc, bfa_mem_dma_virt(ioc_dma), +			bfa_mem_dma_phys(ioc_dma)); -	/* -	 * First allocate dma memory for IOC. -	 */ -	bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa); -	dm_kva += bfa_ioc_meminfo(); -	dm_pa  += bfa_ioc_meminfo(); - -	/* -	 * Claim DMA-able memory for the request/response queues and for shadow -	 * ci/pi registers -	 */ +	/* Claim DMA-able memory for the request/response queues */  	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ), -				  BFA_DMA_ALIGN_SZ); +				BFA_DMA_ALIGN_SZ);  	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ), -				  BFA_DMA_ALIGN_SZ); +				BFA_DMA_ALIGN_SZ);  	for (i = 0; i < cfg->fwcfg.num_cqs; i++) { -		iocfc->req_cq_ba[i].kva = dm_kva; -		iocfc->req_cq_ba[i].pa = dm_pa; -		memset(dm_kva, 0, per_reqq_sz); -		dm_kva += per_reqq_sz; -		dm_pa += per_reqq_sz; - -		iocfc->rsp_cq_ba[i].kva = dm_kva; -		iocfc->rsp_cq_ba[i].pa = dm_pa; -		memset(dm_kva, 0, per_rspq_sz); -		dm_kva += per_rspq_sz; -		dm_pa += per_rspq_sz; +		reqq_dma = BFA_MEM_REQQ_DMA(bfa, i); +		iocfc->req_cq_ba[i].kva = bfa_mem_dma_virt(reqq_dma); +		iocfc->req_cq_ba[i].pa = bfa_mem_dma_phys(reqq_dma); +		memset(iocfc->req_cq_ba[i].kva, 0, per_reqq_sz); + +		rspq_dma = BFA_MEM_RSPQ_DMA(bfa, i); +		iocfc->rsp_cq_ba[i].kva = bfa_mem_dma_virt(rspq_dma); +		iocfc->rsp_cq_ba[i].pa = bfa_mem_dma_phys(rspq_dma); +		memset(iocfc->rsp_cq_ba[i].kva, 0, per_rspq_sz);  	} +	/* Claim IOCFC dma memory - for shadow CI/PI */ +	dm_kva = bfa_mem_dma_virt(iocfc_dma); +	dm_pa  = bfa_mem_dma_phys(iocfc_dma); +  	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {  		iocfc->req_cq_shadow_ci[i].kva = dm_kva;  		iocfc->req_cq_shadow_ci[i].pa = dm_pa; @@ -526,37 +1138,25 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,  		dm_pa += BFA_CACHELINE_SZ;  	} -	/* -	 * Claim DMA-able memory for the config info page -	 */ +	/* Claim IOCFC dma memory - for the config info page */  	bfa->iocfc.cfg_info.kva = dm_kva;  	bfa->iocfc.cfg_info.pa = dm_pa;  	bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;  	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);  	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); -	/* -	 * Claim DMA-able memory for the config response -	 */ +	/* Claim IOCFC dma memory - for the config response */  	bfa->iocfc.cfgrsp_dma.kva = dm_kva;  	bfa->iocfc.cfgrsp_dma.pa = dm_pa;  	bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva; - -	dm_kva += -		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), -			    BFA_CACHELINE_SZ); +	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), +			BFA_CACHELINE_SZ);  	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), -			     BFA_CACHELINE_SZ); +			BFA_CACHELINE_SZ); - -	bfa_meminfo_dma_virt(meminfo) = dm_kva; -	bfa_meminfo_dma_phys(meminfo) = dm_pa; - -	dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover); -	if (dbgsz > 0) { -		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo)); -		bfa_meminfo_kva(meminfo) += dbgsz; -	} +	/* Claim IOCFC kva memory */ +	bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc)); +	bfa_mem_kva_curp(iocfc) += BFA_DBG_FWTRC_LEN;  }  /* @@ -567,10 +1167,14 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)  {  	int		i; -	bfa->rme_process = BFA_TRUE; +	bfa->queue_process = BFA_TRUE; +	for (i = 0; i < BFI_IOC_MAX_CQS; i++) +		bfa_isr_rspq_ack(bfa, i, bfa_rspq_ci(bfa, i));  	for (i = 0; hal_mods[i]; i++)  		hal_mods[i]->start(bfa); + +	bfa->iocfc.submod_enabled = BFA_TRUE;  }  /* @@ -581,8 +1185,13 @@ bfa_iocfc_disable_submod(struct bfa_s *bfa)  {  	int		i; +	if (bfa->iocfc.submod_enabled == BFA_FALSE) +		return; +  	for (i = 0; hal_mods[i]; i++)  		hal_mods[i]->iocdisable(bfa); + +	bfa->iocfc.submod_enabled = BFA_FALSE;  }  static void @@ -590,15 +1199,8 @@ bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)  {  	struct bfa_s	*bfa = bfa_arg; -	if (complete) { -		if (bfa->iocfc.cfgdone) -			bfa_cb_init(bfa->bfad, BFA_STATUS_OK); -		else -			bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED); -	} else { -		if (bfa->iocfc.cfgdone) -			bfa->iocfc.action = BFA_IOCFC_ACT_NONE; -	} +	if (complete) +		bfa_cb_init(bfa->bfad, bfa->iocfc.op_status);  }  static void @@ -609,8 +1211,16 @@ bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)  	if (compl)  		complete(&bfad->comp); -	else -		bfa->iocfc.action = BFA_IOCFC_ACT_NONE; +} + +static void +bfa_iocfc_enable_cb(void *bfa_arg, bfa_boolean_t compl) +{ +	struct bfa_s	*bfa = bfa_arg; +	struct bfad_s *bfad = bfa->bfad; + +	if (compl) +		complete(&bfad->enable_comp);  }  static void @@ -623,6 +1233,41 @@ bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)  		complete(&bfad->disable_comp);  } +/** + * configure queue registers from firmware response + */ +static void +bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg) +{ +	int     i; +	struct bfa_iocfc_regs_s *r = &bfa->iocfc.bfa_regs; +	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); + +	for (i = 0; i < BFI_IOC_MAX_CQS; i++) { +		bfa->iocfc.hw_qid[i] = qreg->hw_qid[i]; +		r->cpe_q_ci[i] = kva + be32_to_cpu(qreg->cpe_q_ci_off[i]); +		r->cpe_q_pi[i] = kva + be32_to_cpu(qreg->cpe_q_pi_off[i]); +		r->cpe_q_ctrl[i] = kva + be32_to_cpu(qreg->cpe_qctl_off[i]); +		r->rme_q_ci[i] = kva + be32_to_cpu(qreg->rme_q_ci_off[i]); +		r->rme_q_pi[i] = kva + be32_to_cpu(qreg->rme_q_pi_off[i]); +		r->rme_q_ctrl[i] = kva + be32_to_cpu(qreg->rme_qctl_off[i]); +	} +} + +static void +bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg) +{ +	struct bfa_iocfc_s	*iocfc   = &bfa->iocfc; +	struct bfi_iocfc_cfg_s	*cfg_info = iocfc->cfginfo; + +	bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs); +	bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs); +	bfa_rport_res_recfg(bfa, fwcfg->num_rports); +	bfa_fcp_res_recfg(bfa, cpu_to_be16(cfg_info->num_ioim_reqs), +			  fwcfg->num_ioim_reqs); +	bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs); +} +  /*   * Update BFA configuration from firmware configuration.   */ @@ -635,23 +1280,34 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)  	fwcfg->num_cqs	      = fwcfg->num_cqs;  	fwcfg->num_ioim_reqs  = be16_to_cpu(fwcfg->num_ioim_reqs); +	fwcfg->num_fwtio_reqs = be16_to_cpu(fwcfg->num_fwtio_reqs);  	fwcfg->num_tskim_reqs = be16_to_cpu(fwcfg->num_tskim_reqs);  	fwcfg->num_fcxp_reqs  = be16_to_cpu(fwcfg->num_fcxp_reqs);  	fwcfg->num_uf_bufs    = be16_to_cpu(fwcfg->num_uf_bufs);  	fwcfg->num_rports     = be16_to_cpu(fwcfg->num_rports); -	iocfc->cfgdone = BFA_TRUE; +	/* +	 * configure queue register offsets as learnt from firmware +	 */ +	bfa_iocfc_qreg(bfa, &cfgrsp->qreg);  	/* -	 * Configuration is complete - initialize/start submodules +	 * Re-configure resources as learnt from Firmware  	 */ -	bfa_fcport_init(bfa); +	bfa_iocfc_res_recfg(bfa, fwcfg); -	if (iocfc->action == BFA_IOCFC_ACT_INIT) -		bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa); -	else -		bfa_iocfc_start_submod(bfa); +	/* +	 * Install MSIX queue handlers +	 */ +	bfa_msix_queue_install(bfa); + +	if (bfa->iocfc.cfgrsp->pbc_cfg.pbc_pwwn != 0) { +		bfa->ioc.attr->pwwn = bfa->iocfc.cfgrsp->pbc_cfg.pbc_pwwn; +		bfa->ioc.attr->nwwn = bfa->iocfc.cfgrsp->pbc_cfg.pbc_nwwn; +		bfa_fsm_send_event(iocfc, IOCFC_E_CFG_DONE); +	}  } +  void  bfa_iocfc_reset_queues(struct bfa_s *bfa)  { @@ -666,6 +1322,95 @@ bfa_iocfc_reset_queues(struct bfa_s *bfa)  }  /* + *	Process FAA pwwn msg from fw. + */ +static void +bfa_iocfc_process_faa_addr(struct bfa_s *bfa, struct bfi_faa_addr_msg_s *msg) +{ +	struct bfa_iocfc_s		*iocfc   = &bfa->iocfc; +	struct bfi_iocfc_cfgrsp_s	*cfgrsp  = iocfc->cfgrsp; + +	cfgrsp->pbc_cfg.pbc_pwwn = msg->pwwn; +	cfgrsp->pbc_cfg.pbc_nwwn = msg->nwwn; + +	bfa->ioc.attr->pwwn = msg->pwwn; +	bfa->ioc.attr->nwwn = msg->nwwn; +	bfa_fsm_send_event(iocfc, IOCFC_E_CFG_DONE); +} + +/* Fabric Assigned Address specific functions */ + +/* + *	Check whether IOC is ready before sending command down + */ +static bfa_status_t +bfa_faa_validate_request(struct bfa_s *bfa) +{ +	enum bfa_ioc_type_e	ioc_type = bfa_get_type(bfa); +	u32	card_type = bfa->ioc.attr->card_type; + +	if (bfa_ioc_is_operational(&bfa->ioc)) { +		if ((ioc_type != BFA_IOC_TYPE_FC) || bfa_mfg_is_mezz(card_type)) +			return BFA_STATUS_FEATURE_NOT_SUPPORTED; +	} else { +		return BFA_STATUS_IOC_NON_OP; +	} + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr, +		bfa_cb_iocfc_t cbfn, void *cbarg) +{ +	struct bfi_faa_query_s  faa_attr_req; +	struct bfa_iocfc_s      *iocfc = &bfa->iocfc; +	bfa_status_t            status; + +	status = bfa_faa_validate_request(bfa); +	if (status != BFA_STATUS_OK) +		return status; + +	if (iocfc->faa_args.busy == BFA_TRUE) +		return BFA_STATUS_DEVBUSY; + +	iocfc->faa_args.faa_attr = attr; +	iocfc->faa_args.faa_cb.faa_cbfn = cbfn; +	iocfc->faa_args.faa_cb.faa_cbarg = cbarg; + +	iocfc->faa_args.busy = BFA_TRUE; +	memset(&faa_attr_req, 0, sizeof(struct bfi_faa_query_s)); +	bfi_h2i_set(faa_attr_req.mh, BFI_MC_IOCFC, +		BFI_IOCFC_H2I_FAA_QUERY_REQ, bfa_fn_lpu(bfa)); + +	bfa_ioc_mbox_send(&bfa->ioc, &faa_attr_req, +		sizeof(struct bfi_faa_query_s)); + +	return BFA_STATUS_OK; +} + +/* + *	FAA query response + */ +static void +bfa_faa_query_reply(struct bfa_iocfc_s *iocfc, +		bfi_faa_query_rsp_t *rsp) +{ +	void	*cbarg = iocfc->faa_args.faa_cb.faa_cbarg; + +	if (iocfc->faa_args.faa_attr) { +		iocfc->faa_args.faa_attr->faa = rsp->faa; +		iocfc->faa_args.faa_attr->faa_state = rsp->faa_status; +		iocfc->faa_args.faa_attr->pwwn_source = rsp->addr_source; +	} + +	WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn); + +	iocfc->faa_args.faa_cb.faa_cbfn(cbarg, BFA_STATUS_OK); +	iocfc->faa_args.busy = BFA_FALSE; +} + +/*   * IOC enable request is complete   */  static void @@ -673,15 +1418,10 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)  {  	struct bfa_s	*bfa = bfa_arg; -	if (status != BFA_STATUS_OK) { -		bfa_isr_disable(bfa); -		if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT) -			bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, -				     bfa_iocfc_init_cb, bfa); -		return; -	} - -	bfa_iocfc_send_cfg(bfa); +	if (status == BFA_STATUS_OK) +		bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_IOC_ENABLED); +	else +		bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_IOC_FAILED);  }  /* @@ -692,17 +1432,8 @@ bfa_iocfc_disable_cbfn(void *bfa_arg)  {  	struct bfa_s	*bfa = bfa_arg; -	bfa_isr_disable(bfa); -	bfa_iocfc_disable_submod(bfa); - -	if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP) -		bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb, -			     bfa); -	else { -		bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE); -		bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb, -			     bfa); -	} +	bfa->queue_process = BFA_FALSE; +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_IOC_DISABLED);  }  /* @@ -713,14 +1444,8 @@ bfa_iocfc_hbfail_cbfn(void *bfa_arg)  {  	struct bfa_s	*bfa = bfa_arg; -	bfa->rme_process = BFA_FALSE; - -	bfa_isr_disable(bfa); -	bfa_iocfc_disable_submod(bfa); - -	if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT) -		bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb, -			     bfa); +	bfa->queue_process = BFA_FALSE; +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_IOC_FAILED);  }  /* @@ -736,22 +1461,49 @@ bfa_iocfc_reset_cbfn(void *bfa_arg)  }  /* - *  hal_ioc_public - */ - -/*   * Query IOC memory requirement information.   */  void -bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -		  u32 *dm_len) +bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, +		  struct bfa_s *bfa)  { -	/* dma memory for IOC */ -	*dm_len += bfa_ioc_meminfo(); +	int q, per_reqq_sz, per_rspq_sz; +	struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa); +	struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa); +	struct bfa_mem_kva_s *iocfc_kva = BFA_MEM_IOCFC_KVA(bfa); +	u32	dm_len = 0; + +	/* dma memory setup for IOC */ +	bfa_mem_dma_setup(meminfo, ioc_dma, +		BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ)); + +	/* dma memory setup for REQ/RSP queues */ +	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ), +				BFA_DMA_ALIGN_SZ); +	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ), +				BFA_DMA_ALIGN_SZ); + +	for (q = 0; q < cfg->fwcfg.num_cqs; q++) { +		bfa_mem_dma_setup(meminfo, BFA_MEM_REQQ_DMA(bfa, q), +				per_reqq_sz); +		bfa_mem_dma_setup(meminfo, BFA_MEM_RSPQ_DMA(bfa, q), +				per_rspq_sz); +	} + +	/* IOCFC dma memory - calculate Shadow CI/PI size */ +	for (q = 0; q < cfg->fwcfg.num_cqs; q++) +		dm_len += (2 * BFA_CACHELINE_SZ); + +	/* IOCFC dma memory - calculate config info / rsp size */ +	dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); +	dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), +			BFA_CACHELINE_SZ); + +	/* dma memory setup for IOCFC */ +	bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len); -	bfa_iocfc_fw_cfg_sz(cfg, dm_len); -	bfa_iocfc_cqs_sz(cfg, dm_len); -	*km_len += bfa_ioc_debug_trcsz(bfa_auto_recover); +	/* kva memory setup for IOCFC */ +	bfa_mem_kva_setup(meminfo, iocfc_kva, BFA_DBG_FWTRC_LEN);  }  /* @@ -759,7 +1511,7 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,   */  void  bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -		 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) +		 struct bfa_pcidev_s *pcidev)  {  	int		i;  	struct bfa_ioc_s *ioc = &bfa->ioc; @@ -772,31 +1524,22 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	ioc->trcmod = bfa->trcmod;  	bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod); -	/* -	 * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC. -	 */ -	if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC) -		bfa_ioc_set_fcmode(&bfa->ioc); - -	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC); +	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_PCIFN_CLASS_FC);  	bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);  	bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev); -	bfa_iocfc_mem_claim(bfa, cfg, meminfo); -	bfa_timer_init(&bfa->timer_mod); +	bfa_iocfc_mem_claim(bfa, cfg); +	INIT_LIST_HEAD(&bfa->timer_mod.timer_q);  	INIT_LIST_HEAD(&bfa->comp_q);  	for (i = 0; i < BFI_IOC_MAX_CQS; i++)  		INIT_LIST_HEAD(&bfa->reqq_waitq[i]); -} -/* - * Query IOC memory requirement information. - */ -void -bfa_iocfc_detach(struct bfa_s *bfa) -{ -	bfa_ioc_detach(&bfa->ioc); +	bfa->iocfc.cb_reqd = BFA_FALSE; +	bfa->iocfc.op_status = BFA_STATUS_OK; +	bfa->iocfc.submod_enabled = BFA_FALSE; + +	bfa_fsm_set_state(&bfa->iocfc, bfa_iocfc_sm_stopped);  }  /* @@ -805,8 +1548,7 @@ bfa_iocfc_detach(struct bfa_s *bfa)  void  bfa_iocfc_init(struct bfa_s *bfa)  { -	bfa->iocfc.action = BFA_IOCFC_ACT_INIT; -	bfa_ioc_enable(&bfa->ioc); +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_INIT);  }  /* @@ -816,8 +1558,7 @@ bfa_iocfc_init(struct bfa_s *bfa)  void  bfa_iocfc_start(struct bfa_s *bfa)  { -	if (bfa->iocfc.cfgdone) -		bfa_iocfc_start_submod(bfa); +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_START);  }  /* @@ -827,10 +1568,7 @@ bfa_iocfc_start(struct bfa_s *bfa)  void  bfa_iocfc_stop(struct bfa_s *bfa)  { -	bfa->iocfc.action = BFA_IOCFC_ACT_STOP; - -	bfa->rme_process = BFA_FALSE; -	bfa_ioc_disable(&bfa->ioc); +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_STOP);  }  void @@ -845,30 +1583,24 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)  	switch (msg->mh.msg_id) {  	case BFI_IOCFC_I2H_CFG_REPLY: -		iocfc->cfg_reply = &msg->cfg_reply;  		bfa_iocfc_cfgrsp(bfa);  		break;  	case BFI_IOCFC_I2H_UPDATEQ_RSP:  		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);  		break; +	case BFI_IOCFC_I2H_ADDR_MSG: +		bfa_iocfc_process_faa_addr(bfa, +				(struct bfi_faa_addr_msg_s *)msg); +		break; +	case BFI_IOCFC_I2H_FAA_QUERY_RSP: +		bfa_faa_query_reply(iocfc, (bfi_faa_query_rsp_t *)msg); +		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  	}  }  void -bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr) -{ -	bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr); -} - -u64 -bfa_adapter_get_id(struct bfa_s *bfa) -{ -	return bfa_ioc_get_adid(&bfa->ioc); -} - -void  bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)  {  	struct bfa_iocfc_s	*iocfc = &bfa->iocfc; @@ -904,7 +1636,7 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)  		return BFA_STATUS_DEVBUSY;  	bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ, -		    bfa_lpuid(bfa)); +		    bfa_fn_lpu(bfa));  	m->coalesce = iocfc->cfginfo->intr_attr.coalesce;  	m->delay    = iocfc->cfginfo->intr_attr.delay;  	m->latency  = iocfc->cfginfo->intr_attr.latency; @@ -912,17 +1644,17 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)  	bfa_trc(bfa, attr->delay);  	bfa_trc(bfa, attr->latency); -	bfa_reqq_produce(bfa, BFA_REQQ_IOC); +	bfa_reqq_produce(bfa, BFA_REQQ_IOC, m->mh);  	return BFA_STATUS_OK;  }  void -bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa) +bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa)  {  	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;  	iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1); -	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa); +	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase[seg_no], snsbase_pa);  }  /*   * Enable IOC after it is disabled. @@ -932,7 +1664,8 @@ bfa_iocfc_enable(struct bfa_s *bfa)  {  	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,  		     "IOC Enable"); -	bfa_ioc_enable(&bfa->ioc); +	bfa->iocfc.cb_reqd = BFA_TRUE; +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_ENABLE);  }  void @@ -940,17 +1673,15 @@ bfa_iocfc_disable(struct bfa_s *bfa)  {  	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,  		     "IOC Disable"); -	bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE; -	bfa->rme_process = BFA_FALSE; -	bfa_ioc_disable(&bfa->ioc); +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DISABLE);  } -  bfa_boolean_t  bfa_iocfc_is_operational(struct bfa_s *bfa)  { -	return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone; +	return bfa_ioc_is_operational(&bfa->ioc) && +		bfa_fsm_cmp_state(&bfa->iocfc, bfa_iocfc_sm_operational);  }  /* @@ -976,18 +1707,6 @@ bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)  	memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));  } -void -bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg) -{ -	struct bfa_iocfc_s *iocfc = &bfa->iocfc; -	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; - -	pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled; -	pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns; -	pbcfg->speed = cfgrsp->pbc_cfg.port_speed; -	memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun)); -} -  int  bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)  { @@ -998,9 +1717,6 @@ bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)  	return cfgrsp->pbc_cfg.nvports;  } -/* - *  hal_api - */  /*   * Use this function query the memory requirement of the BFA library. @@ -1026,33 +1742,52 @@ bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)   *			starting address for each block and provide the same   *			structure as input parameter to bfa_attach() call.   * + * @param[in] bfa -	pointer to the bfa structure, used while fetching the + *			dma, kva memory information of the bfa sub-modules. + *   * @return void   *   * Special Considerations: @note   */  void -bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo) +bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, +		struct bfa_s *bfa)  {  	int		i; -	u32	km_len = 0, dm_len = 0; +	struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa); +	struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa); +	struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa); +	struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa); +	struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa); +	struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa); +	struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa); +	struct bfa_mem_dma_s *fru_dma = BFA_MEM_FRU_DMA(bfa); -	bfa_assert((cfg != NULL) && (meminfo != NULL)); +	WARN_ON((cfg == NULL) || (meminfo == NULL));  	memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s)); -	meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type = -		BFA_MEM_TYPE_KVA; -	meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type = -		BFA_MEM_TYPE_DMA; -	bfa_iocfc_meminfo(cfg, &km_len, &dm_len); +	/* Initialize the DMA & KVA meminfo queues */ +	INIT_LIST_HEAD(&meminfo->dma_info.qe); +	INIT_LIST_HEAD(&meminfo->kva_info.qe); -	for (i = 0; hal_mods[i]; i++) -		hal_mods[i]->meminfo(cfg, &km_len, &dm_len); +	bfa_iocfc_meminfo(cfg, meminfo, bfa); -	dm_len += bfa_port_meminfo(); - -	meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len; -	meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len; +	for (i = 0; hal_mods[i]; i++) +		hal_mods[i]->meminfo(cfg, meminfo, bfa); + +	/* dma info setup */ +	bfa_mem_dma_setup(meminfo, port_dma, bfa_port_meminfo()); +	bfa_mem_dma_setup(meminfo, ablk_dma, bfa_ablk_meminfo()); +	bfa_mem_dma_setup(meminfo, cee_dma, bfa_cee_meminfo()); +	bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo()); +	bfa_mem_dma_setup(meminfo, flash_dma, +			  bfa_flash_meminfo(cfg->drvcfg.min_cfg)); +	bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo()); +	bfa_mem_dma_setup(meminfo, phy_dma, +			  bfa_phy_meminfo(cfg->drvcfg.min_cfg)); +	bfa_mem_dma_setup(meminfo, fru_dma, +			  bfa_fru_meminfo(cfg->drvcfg.min_cfg));  }  /* @@ -1085,28 +1820,47 @@ void  bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	       struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)  { -	int			i; -	struct bfa_mem_elem_s	*melem; +	int	i; +	struct bfa_mem_dma_s *dma_info, *dma_elem; +	struct bfa_mem_kva_s *kva_info, *kva_elem; +	struct list_head *dm_qe, *km_qe;  	bfa->fcs = BFA_FALSE; -	bfa_assert((cfg != NULL) && (meminfo != NULL)); +	WARN_ON((cfg == NULL) || (meminfo == NULL)); -	/* -	 * initialize all memory pointers for iterative allocation -	 */ -	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) { -		melem = meminfo->meminfo + i; -		melem->kva_curp = melem->kva; -		melem->dma_curp = melem->dma; +	/* Initialize memory pointers for iterative allocation */ +	dma_info = &meminfo->dma_info; +	dma_info->kva_curp = dma_info->kva; +	dma_info->dma_curp = dma_info->dma; + +	kva_info = &meminfo->kva_info; +	kva_info->kva_curp = kva_info->kva; + +	list_for_each(dm_qe, &dma_info->qe) { +		dma_elem = (struct bfa_mem_dma_s *) dm_qe; +		dma_elem->kva_curp = dma_elem->kva; +		dma_elem->dma_curp = dma_elem->dma; +	} + +	list_for_each(km_qe, &kva_info->qe) { +		kva_elem = (struct bfa_mem_kva_s *) km_qe; +		kva_elem->kva_curp = kva_elem->kva;  	} -	bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev); +	bfa_iocfc_attach(bfa, bfad, cfg, pcidev);  	for (i = 0; hal_mods[i]; i++) -		hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev); +		hal_mods[i]->attach(bfa, bfad, cfg, pcidev); -	bfa_com_port_attach(bfa, meminfo); +	bfa_com_port_attach(bfa); +	bfa_com_ablk_attach(bfa); +	bfa_com_cee_attach(bfa); +	bfa_com_sfp_attach(bfa); +	bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg); +	bfa_com_diag_attach(bfa); +	bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg); +	bfa_com_fru_attach(bfa, cfg->drvcfg.min_cfg);  }  /* @@ -1129,79 +1883,7 @@ bfa_detach(struct bfa_s *bfa)  	for (i = 0; hal_mods[i]; i++)  		hal_mods[i]->detach(bfa); - -	bfa_iocfc_detach(bfa); -} - - -void -bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod) -{ -	bfa->trcmod = trcmod; -} - -void -bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog) -{ -	bfa->plog = plog; -} - -/* - * Initialize IOC. - * - * This function will return immediately, when the IOC initialization is - * completed, the bfa_cb_init() will be called. - * - * @param[in]	bfa	instance - * - * @return void - * - * Special Considerations: - * - * @note - * When this function returns, the driver should register the interrupt service - * routine(s) and enable the device interrupts. If this is not done, - * bfa_cb_init() will never get called - */ -void -bfa_init(struct bfa_s *bfa) -{ -	bfa_iocfc_init(bfa); -} - -/* - * Use this function initiate the IOC configuration setup. This function - * will return immediately. - * - * @param[in]	bfa	instance - * - * @return None - */ -void -bfa_start(struct bfa_s *bfa) -{ -	bfa_iocfc_start(bfa); -} - -/* - * Use this function quiese the IOC. This function will return immediately, - * when the IOC is actually stopped, the bfad->comp will be set. - * - * @param[in]bfa - pointer to bfa_t. - * - * @return None - * - * Special Considerations: - * bfad->comp can be set before or after bfa_stop() returns. - * - * @note - * In case of any failure, we could handle it automatically by doing a - * reset and then succeed the bfa_stop() call. - */ -void -bfa_stop(struct bfa_s *bfa) -{ -	bfa_iocfc_stop(bfa); +	bfa_ioc_detach(&bfa->ioc);  }  void @@ -1217,10 +1899,17 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)  	struct list_head		*qe;  	struct list_head		*qen;  	struct bfa_cb_qe_s	*hcb_qe; +	bfa_cb_cbfn_status_t	cbfn;  	list_for_each_safe(qe, qen, comp_q) {  		hcb_qe = (struct bfa_cb_qe_s *) qe; -		hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE); +		if (hcb_qe->pre_rmv) { +			/* qe is invalid after return, dequeue before cbfn() */ +			list_del(qe); +			cbfn = (bfa_cb_cbfn_status_t)(hcb_qe->cbfn); +			cbfn(hcb_qe->cbarg, hcb_qe->fw_status); +		} else +			hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);  	}  } @@ -1233,25 +1922,11 @@ bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)  	while (!list_empty(comp_q)) {  		bfa_q_deq(comp_q, &qe);  		hcb_qe = (struct bfa_cb_qe_s *) qe; +		WARN_ON(hcb_qe->pre_rmv);  		hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE);  	}  } -void -bfa_attach_fcs(struct bfa_s *bfa) -{ -	bfa->fcs = BFA_TRUE; -} - -/* - * Periodic timer heart beat from driver - */ -void -bfa_timer_tick(struct bfa_s *bfa) -{ -	bfa_timer_beat(&bfa->timer_mod); -} -  /*   * Return the list of PCI vendor/device id lists supported by this   * BFA instance. @@ -1294,6 +1969,7 @@ bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)  	cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS;  	cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS;  	cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS; +	cfg->fwcfg.num_fwtio_reqs = 0;  	cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS;  	cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS; @@ -1315,95 +1991,10 @@ bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)  	cfg->fwcfg.num_fcxp_reqs   = BFA_FCXP_MIN;  	cfg->fwcfg.num_uf_bufs     = BFA_UF_MIN;  	cfg->fwcfg.num_rports      = BFA_RPORT_MIN; +	cfg->fwcfg.num_fwtio_reqs = 0;  	cfg->drvcfg.num_sgpgs      = BFA_SGPG_MIN;  	cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;  	cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;  	cfg->drvcfg.min_cfg	   = BFA_TRUE;  } - -void -bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr) -{ -	bfa_ioc_get_attr(&bfa->ioc, ioc_attr); -} - -/* - * Retrieve firmware trace information on IOC failure. - */ -bfa_status_t -bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen) -{ -	return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen); -} - -/* - * Clear the saved firmware trace information of an IOC. - */ -void -bfa_debug_fwsave_clear(struct bfa_s *bfa) -{ -	bfa_ioc_debug_fwsave_clear(&bfa->ioc); -} - -/* - * Fetch firmware trace data. - * - * @param[in]		bfa			BFA instance - * @param[out]		trcdata		Firmware trace buffer - * @param[in,out]	trclen		Firmware trace buffer len - * - * @retval BFA_STATUS_OK			Firmware trace is fetched. - * @retval BFA_STATUS_INPROGRESS	Firmware trace fetch is in progress. - */ -bfa_status_t -bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen) -{ -	return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen); -} - -/* - * Dump firmware memory. - * - * @param[in]		bfa		BFA instance - * @param[out]		buf		buffer for dump - * @param[in,out]	offset		smem offset to start read - * @param[in,out]	buflen		length of buffer - * - * @retval BFA_STATUS_OK		Firmware memory is dumped. - * @retval BFA_STATUS_INPROGRESS	Firmware memory dump is in progress. - */ -bfa_status_t -bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen) -{ -	return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen); -} -/* - * Reset hw semaphore & usage cnt regs and initialize. - */ -void -bfa_chip_reset(struct bfa_s *bfa) -{ -	bfa_ioc_ownership_reset(&bfa->ioc); -	bfa_ioc_pll_init(&bfa->ioc); -} - -/* - * Fetch firmware statistics data. - * - * @param[in]		bfa		BFA instance - * @param[out]		data		Firmware stats buffer - * - * @retval BFA_STATUS_OK		Firmware trace is fetched. - */ -bfa_status_t -bfa_fw_stats_get(struct bfa_s *bfa, void *data) -{ -	return bfa_ioc_fw_stats_get(&bfa->ioc, data); -} - -bfa_status_t -bfa_fw_stats_clear(struct bfa_s *bfa) -{ -	return bfa_ioc_fw_stats_clear(&bfa->ioc); -} diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h index 99f242b9aa3..91a8aa394db 100644 --- a/drivers/scsi/bfa/bfa_cs.h +++ b/drivers/scsi/bfa/bfa_cs.h @@ -22,7 +22,7 @@  #ifndef __BFA_CS_H__  #define __BFA_CS_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h"  /*   * BFA TRC @@ -32,12 +32,20 @@  #define BFA_TRC_MAX	(4 * 1024)  #endif +#define BFA_TRC_TS(_trcm)                               \ +	({                                              \ +		struct timeval tv;                      \ +							\ +		do_gettimeofday(&tv);                   \ +		(tv.tv_sec*1000000+tv.tv_usec);         \ +	}) +  #ifndef BFA_TRC_TS  #define BFA_TRC_TS(_trcm)	((_trcm)->ticks++)  #endif  struct bfa_trc_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u16	fileno;  	u16	line;  #else @@ -99,13 +107,6 @@ bfa_trc_stop(struct bfa_trc_mod_s *trcm)  	trcm->stopped = 1;  } -#ifdef FWTRC -extern void dc_flush(void *data); -#else -#define dc_flush(data) -#endif - -  static inline void  __bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)  { @@ -119,12 +120,10 @@ __bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)  	trc->line = (u16) line;  	trc->data.u64 = data;  	trc->timestamp = BFA_TRC_TS(trcm); -	dc_flush(trc);  	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);  	if (trcm->tail == trcm->head)  		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1); -	dc_flush(trcm);  } @@ -141,42 +140,18 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)  	trc->line = (u16) line;  	trc->data.u32.u32 = data;  	trc->timestamp = BFA_TRC_TS(trcm); -	dc_flush(trc);  	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);  	if (trcm->tail == trcm->head)  		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1); -	dc_flush(trcm);  } -#ifndef BFA_PERF_BUILD -#define bfa_trc_fp(_trcp, _data)	bfa_trc(_trcp, _data) -#else -#define bfa_trc_fp(_trcp, _data) -#endif - -/* - * @ BFA LOG interfaces - */ -#define bfa_assert(__cond)	do {					\ -	if (!(__cond)) {						\ -		printk(KERN_ERR "assert(%s) failed at %s:%d\\n",         \ -		#__cond, __FILE__, __LINE__);				\ -	}								\ -} while (0) -  #define bfa_sm_fault(__mod, __event)	do {				\  	bfa_trc(__mod, (((u32)0xDEAD << 16) | __event));		\  	printk(KERN_ERR	"Assertion failure: %s:%d: %d",			\  		__FILE__, __LINE__, (__event));				\  } while (0) -#ifndef BFA_PERF_BUILD -#define bfa_assert_fp(__cond)	bfa_assert(__cond) -#else -#define bfa_assert_fp(__cond) -#endif -  /* BFA queue definitions */  #define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))  #define bfa_q_next(_qe) (((struct list_head *) (_qe))->next) @@ -193,17 +168,16 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)  /*   * bfa_q_deq - dequeue an element from head of the queue   */ -#define bfa_q_deq(_q, _qe) {						\ +#define bfa_q_deq(_q, _qe) do {						\  	if (!list_empty(_q)) {						\  		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\  		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\  				(struct list_head *) (_q);		\  		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\ -		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\  	} else {							\  		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\  	}								\ -} +} while (0)  /*   * bfa_q_deq_tail - dequeue an element from tail of the queue @@ -214,7 +188,6 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)  		bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) =	\  			(struct list_head *) (_q);			\  		bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\ -		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\  	} else {							\  		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\  	}								\ @@ -236,16 +209,6 @@ bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)  	return 0;  } -/* - * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not - * consistent across modules) - */ -#ifndef BFA_PERF_BUILD -#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe) -#else -#define BFA_Q_DBG_INIT(_qe) -#endif -  #define bfa_q_is_on_q(_q, _qe)      \  	bfa_q_is_on_q_func(_q, (struct list_head *)(_qe)) @@ -361,4 +324,43 @@ bfa_wc_wait(struct bfa_wc_s *wc)  	bfa_wc_down(wc);  } +static inline void +wwn2str(char *wwn_str, u64 wwn) +{ +	union { +		u64 wwn; +		u8 byte[8]; +	} w; + +	w.wwn = wwn; +	sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0], +		w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5], +		w.byte[6], w.byte[7]); +} + +static inline void +fcid2str(char *fcid_str, u32 fcid) +{ +	union { +		u32 fcid; +		u8 byte[4]; +	} f; + +	f.fcid = fcid; +	sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]); +} + +#define bfa_swap_3b(_x)				\ +	((((_x) & 0xff) << 16) |		\ +	((_x) & 0x00ff00) |			\ +	(((_x) & 0xff0000) >> 16)) + +#ifndef __BIG_ENDIAN +#define bfa_hton3b(_x)  bfa_swap_3b(_x) +#else +#define bfa_hton3b(_x)  (_x) +#endif + +#define bfa_ntoh3b(_x)  bfa_hton3b(_x) +  #endif /* __BFA_CS_H__ */ diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index 4b5b9e35abb..877b86dd283 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -19,7 +19,7 @@  #define __BFA_DEFS_H__  #include "bfa_fc.h" -#include "bfa_os_inc.h" +#include "bfad_drv.h"  #define BFA_MFG_SERIALNUM_SIZE                  11  #define STRSZ(_n)                               (((_n) + 4) & ~3) @@ -40,7 +40,13 @@ enum {  	BFA_MFG_TYPE_ASTRA    = 807,     /*  Astra mezz card            */  	BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*  Lightning mezz card - old  */  	BFA_MFG_TYPE_LIGHTNING = 1741,   /*  Lightning mezz card        */ -	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type          */ +	BFA_MFG_TYPE_PROWLER_F = 1560,	 /*  Prowler FC only cards	*/ +	BFA_MFG_TYPE_PROWLER_N = 1410,	 /*  Prowler NIC only cards	*/ +	BFA_MFG_TYPE_PROWLER_C = 1710,   /*  Prowler CNA only cards	*/ +	BFA_MFG_TYPE_PROWLER_D = 1860,   /*  Prowler Dual cards		*/ +	BFA_MFG_TYPE_CHINOOK   = 1867,   /*  Chinook cards		*/ +	BFA_MFG_TYPE_CHINOOK2   = 1869,	 /*!< Chinook2 cards		*/ +	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type		*/  };  #pragma pack(1) @@ -53,7 +59,9 @@ enum {  	(type) == BFA_MFG_TYPE_WANCHESE || \  	(type) == BFA_MFG_TYPE_ASTRA || \  	(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \ -	(type) == BFA_MFG_TYPE_LIGHTNING)) +	(type) == BFA_MFG_TYPE_LIGHTNING || \ +	(type) == BFA_MFG_TYPE_CHINOOK || \ +	(type) == BFA_MFG_TYPE_CHINOOK2))  /*   * Check if the card having old wwn/mac handling @@ -124,30 +132,104 @@ enum bfa_status {  	BFA_STATUS_ETIMER	= 5,	/*  Timer expired - Retry, if persists,  					 *  contact support */  	BFA_STATUS_EPROTOCOL	= 6,	/*  Protocol error */ +	BFA_STATUS_BADFLASH	= 9,	/*  Flash is bad */ +	BFA_STATUS_SFP_UNSUPP	= 10,	/*  Unsupported SFP - Replace SFP */ +	BFA_STATUS_UNKNOWN_VFID = 11,	/*  VF_ID not found */ +	BFA_STATUS_DATACORRUPTED = 12,  /*  Diag returned data corrupted */  	BFA_STATUS_DEVBUSY	= 13,	/*  Device busy - Retry operation */ +	BFA_STATUS_HDMA_FAILED  = 16,   /* Host dma failed contact support */ +	BFA_STATUS_FLASH_BAD_LEN = 17,	/*  Flash bad length */  	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */  	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */  	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */  	BFA_STATUS_VPORT_MAX	= 22,	/*  Reached max VPORT supported limit */  	BFA_STATUS_UNSUPP_SPEED	= 23,	/*  Invalid Speed Check speed setting */  	BFA_STATUS_INVLD_DFSZ	= 24,	/*  Invalid Max data field size */ +	BFA_STATUS_CMD_NOTSUPP  = 26,   /*  Command/API not supported */  	BFA_STATUS_FABRIC_RJT	= 29,	/*  Reject from attached fabric */ +	BFA_STATUS_UNKNOWN_VWWN = 30,	/*  VPORT PWWN not found */ +	BFA_STATUS_PORT_OFFLINE = 34,	/*  Port is not online */  	BFA_STATUS_VPORT_WWN_BP	= 46,	/*  WWN is same as base port's WWN */ +	BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port */  	BFA_STATUS_NO_FCPIM_NEXUS = 52,	/* No FCP Nexus exists with the rport */  	BFA_STATUS_IOC_FAILURE	= 56,	/* IOC failure - Retry, if persists  					 * contact support */  	BFA_STATUS_INVALID_WWN	= 57,	/*  Invalid WWN */ +	BFA_STATUS_ADAPTER_ENABLED = 60, /* Adapter is not disabled */ +	BFA_STATUS_IOC_NON_OP   = 61,	/* IOC is not operational */ +	BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */  	BFA_STATUS_DIAG_BUSY	= 71,	/*  diag busy */ +	BFA_STATUS_BEACON_ON    = 72,   /* Port Beacon already on */  	BFA_STATUS_ENOFSAVE	= 78,	/*  No saved firmware trace */  	BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */ +	BFA_STATUS_ERROR_TRL_ENABLED  = 87,   /* TRL is enabled */ +	BFA_STATUS_ERROR_QOS_ENABLED  = 88,   /* QoS is enabled */ +	BFA_STATUS_NO_SFP_DEV = 89,	/* No SFP device check or replace SFP */ +	BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */ +	BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */  	BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */ +	BFA_STATUS_CMD_NOTSUPP_CNA = 146, /* Command not supported for CNA */  	BFA_STATUS_PBC		= 154, /*  Operation not allowed for pre-boot  					*  configuration */ +	BFA_STATUS_BAD_FWCFG = 156,	/* Bad firmware configuration */ +	BFA_STATUS_INVALID_VENDOR = 158, /* Invalid switch vendor */ +	BFA_STATUS_SFP_NOT_READY = 159,	/* SFP info is not ready. Retry */  	BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on  					 * this adapter */  	BFA_STATUS_TRUNK_DISABLED  = 165, /* Trunking is disabled on  					   * the adapter */  	BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */ +	BFA_STATUS_PHY_NOT_PRESENT = 183, /* PHY module not present */ +	BFA_STATUS_FEATURE_NOT_SUPPORTED = 192,	/* Feature not supported */ +	BFA_STATUS_ENTRY_EXISTS = 193,	/* Entry already exists */ +	BFA_STATUS_ENTRY_NOT_EXISTS = 194, /* Entry does not exist */ +	BFA_STATUS_NO_CHANGE = 195,	/* Feature already in that state */ +	BFA_STATUS_FAA_ENABLED = 197,	/* FAA is already enabled */ +	BFA_STATUS_FAA_DISABLED = 198,	/* FAA is already disabled */ +	BFA_STATUS_FAA_ACQUIRED = 199,	/* FAA is already acquired */ +	BFA_STATUS_FAA_ACQ_ADDR = 200,	/* Acquiring addr */ +	BFA_STATUS_BBCR_FC_ONLY = 201, /*!< BBCredit Recovery is supported for * +					* FC mode only */ +	BFA_STATUS_ERROR_TRUNK_ENABLED = 203,	/* Trunk enabled on adapter */ +	BFA_STATUS_MAX_ENTRY_REACHED = 212,	/* MAX entry reached */ +	BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */ +	BFA_STATUS_LOOP_UNSUPP_MEZZ = 231, /* Loop topology is not supported +					    * on mezz cards */ +	BFA_STATUS_INVALID_BW = 233,	/* Invalid bandwidth value */ +	BFA_STATUS_QOS_BW_INVALID = 234,   /* Invalid QOS bandwidth +					    * configuration */ +	BFA_STATUS_DPORT_ENABLED = 235, /* D-port mode is already enabled */ +	BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */ +	BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */ +	BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */ +	BFA_STATUS_DPORT_NO_SFP = 243, /* SFP is not present.\n D-port will be +					* enabled but it will be operational +					* only after inserting a valid SFP. */ +	BFA_STATUS_DPORT_ERR = 245,	/* D-port mode is enabled */ +	BFA_STATUS_DPORT_ENOSYS = 254, /* Switch has no D_Port functionality */ +	BFA_STATUS_DPORT_CANT_PERF = 255, /* Switch port is not D_Port capable +					* or D_Port is disabled */ +	BFA_STATUS_DPORT_LOGICALERR = 256, /* Switch D_Port fail */ +	BFA_STATUS_DPORT_SWBUSY = 257, /* Switch port busy */ +	BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT = 258, /*!< BB credit recovery is +					* supported at max port speed alone */ +	BFA_STATUS_ERROR_BBCR_ENABLED  = 259, /*!< BB credit recovery +					* is enabled */ +	BFA_STATUS_INVALID_BBSCN = 260, /*!< Invalid BBSCN value. +					 * Valid range is [1-15] */ +	BFA_STATUS_DDPORT_ERR = 261, /* Dynamic D_Port mode is active.\n To +					* exit dynamic mode, disable D_Port on +					* the remote port */ +	BFA_STATUS_DPORT_SFPWRAP_ERR = 262, /* Clear e/o_wrap fail, check or +						* replace SFP */ +	BFA_STATUS_BBCR_CFG_NO_CHANGE = 265, /*!< BBCR is operational. +			* Disable BBCR and try this operation again. */ +	BFA_STATUS_DPORT_SW_NOTREADY = 268, /* Remote port is not ready to +					* start dport test. Check remote +					* port status. */ +	BFA_STATUS_DPORT_INV_SFP = 271, /* Invalid SFP for D-PORT mode. */ +	BFA_STATUS_DPORT_CMD_NOTSUPP    = 273, /* Dport is not supported by +					* remote port */  	BFA_STATUS_MAX_VAL		/* Unknown error code */  };  #define bfa_status_t enum bfa_status @@ -184,6 +266,7 @@ enum {  	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*  manufacturer name length */  	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*  adapter symbolic name length */  	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*  adapter os type length */ +	BFA_ADAPTER_UUID_LEN	    = 16,  /* adapter uuid length */  };  struct bfa_adapter_attr_s { @@ -213,6 +296,11 @@ struct bfa_adapter_attr_s {  	u8		is_mezz;  	u8		trunk_capable; +	u8		mfg_day;	/* manufacturing day */ +	u8		mfg_month;	/* manufacturing month */ +	u16		mfg_year;	/* manufacturing year */ +	u16		rsvd; +	u8		uuid[BFA_ADAPTER_UUID_LEN];  };  /* @@ -265,6 +353,8 @@ enum bfa_ioc_state {  	BFA_IOC_DISABLED	= 10,	/*  IOC is disabled */  	BFA_IOC_FWMISMATCH	= 11,	/*  IOC f/w different from drivers */  	BFA_IOC_ENABLING	= 12,	/*  IOC is being enabled */ +	BFA_IOC_HWFAIL		= 13,	/*  PCI mapping doesn't exist */ +	BFA_IOC_ACQ_ADDR	= 14,	/*  Acquiring addr from fabric */  };  /* @@ -294,6 +384,7 @@ struct bfa_ioc_drv_stats_s {  	u32	enable_reqs;  	u32	disable_replies;  	u32	enable_replies; +	u32	rsvd;  };  /* @@ -320,7 +411,144 @@ struct bfa_ioc_attr_s {  	struct bfa_ioc_driver_attr_s	driver_attr;	/*  driver attr    */  	struct bfa_ioc_pci_attr_s	pci_attr;  	u8				port_id;	/*  port number    */ -	u8				rsvd[7];	/*  64bit align    */ +	u8				port_mode;	/*  bfa_mode_s	*/ +	u8				cap_bm;		/*  capability	*/ +	u8				port_mode_cfg;	/*  bfa_mode_s	*/ +	u8				def_fn;		/* 1 if default fn */ +	u8				rsvd[3];	/*  64bit align	*/ +}; + +/* + *			AEN related definitions + */ +enum bfa_aen_category { +	BFA_AEN_CAT_ADAPTER	= 1, +	BFA_AEN_CAT_PORT	= 2, +	BFA_AEN_CAT_LPORT	= 3, +	BFA_AEN_CAT_RPORT	= 4, +	BFA_AEN_CAT_ITNIM	= 5, +	BFA_AEN_CAT_AUDIT	= 8, +	BFA_AEN_CAT_IOC		= 9, +}; + +/* BFA adapter level events */ +enum bfa_adapter_aen_event { +	BFA_ADAPTER_AEN_ADD	= 1,	/* New Adapter found event */ +	BFA_ADAPTER_AEN_REMOVE	= 2,	/* Adapter removed event */ +}; + +struct bfa_adapter_aen_data_s { +	char	serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; +	u32	nports; /* Number of NPorts */ +	wwn_t	pwwn;   /* WWN of one of its physical port */ +}; + +/* BFA physical port Level events */ +enum bfa_port_aen_event { +	BFA_PORT_AEN_ONLINE	= 1,    /* Physical Port online event */ +	BFA_PORT_AEN_OFFLINE	= 2,    /* Physical Port offline event */ +	BFA_PORT_AEN_RLIR	= 3,    /* RLIR event, not supported */ +	BFA_PORT_AEN_SFP_INSERT	= 4,    /* SFP inserted event */ +	BFA_PORT_AEN_SFP_REMOVE	= 5,    /* SFP removed event */ +	BFA_PORT_AEN_SFP_POM	= 6,    /* SFP POM event */ +	BFA_PORT_AEN_ENABLE	= 7,    /* Physical Port enable event */ +	BFA_PORT_AEN_DISABLE	= 8,    /* Physical Port disable event */ +	BFA_PORT_AEN_AUTH_ON	= 9,    /* Physical Port auth success event */ +	BFA_PORT_AEN_AUTH_OFF	= 10,   /* Physical Port auth fail event */ +	BFA_PORT_AEN_DISCONNECT	= 11,   /* Physical Port disconnect event */ +	BFA_PORT_AEN_QOS_NEG	= 12,   /* Base Port QOS negotiation event */ +	BFA_PORT_AEN_FABRIC_NAME_CHANGE	= 13, /* Fabric Name/WWN change */ +	BFA_PORT_AEN_SFP_ACCESS_ERROR	= 14, /* SFP read error event */ +	BFA_PORT_AEN_SFP_UNSUPPORT	= 15, /* Unsupported SFP event */ +}; + +enum bfa_port_aen_sfp_pom { +	BFA_PORT_AEN_SFP_POM_GREEN = 1, /* Normal */ +	BFA_PORT_AEN_SFP_POM_AMBER = 2, /* Warning */ +	BFA_PORT_AEN_SFP_POM_RED   = 3, /* Critical */ +	BFA_PORT_AEN_SFP_POM_MAX   = BFA_PORT_AEN_SFP_POM_RED +}; + +struct bfa_port_aen_data_s { +	wwn_t		pwwn;		/* WWN of the physical port */ +	wwn_t		fwwn;		/* WWN of the fabric port */ +	u32		phy_port_num;	/* For SFP related events */ +	u16		ioc_type; +	u16		level;		/* Only transitions will be informed */ +	mac_t		mac;		/* MAC address of the ethernet port */ +	u16		rsvd; +}; + +/* BFA AEN logical port events */ +enum bfa_lport_aen_event { +	BFA_LPORT_AEN_NEW	= 1,		/* LPort created event */ +	BFA_LPORT_AEN_DELETE	= 2,		/* LPort deleted event */ +	BFA_LPORT_AEN_ONLINE	= 3,		/* LPort online event */ +	BFA_LPORT_AEN_OFFLINE	= 4,		/* LPort offline event */ +	BFA_LPORT_AEN_DISCONNECT = 5,		/* LPort disconnect event */ +	BFA_LPORT_AEN_NEW_PROP	= 6,		/* VPort created event */ +	BFA_LPORT_AEN_DELETE_PROP = 7,		/* VPort deleted event */ +	BFA_LPORT_AEN_NEW_STANDARD = 8,		/* VPort created event */ +	BFA_LPORT_AEN_DELETE_STANDARD = 9,	/* VPort deleted event */ +	BFA_LPORT_AEN_NPIV_DUP_WWN = 10,	/* VPort with duplicate WWN */ +	BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11,	/* Max NPIV in fabric/fport */ +	BFA_LPORT_AEN_NPIV_UNKNOWN = 12,	/* Unknown NPIV Error code */ +}; + +struct bfa_lport_aen_data_s { +	u16	vf_id;	/* vf_id of this logical port */ +	u16	roles;	/* Logical port mode,IM/TM/IP etc */ +	u32	rsvd; +	wwn_t	ppwwn;	/* WWN of its physical port */ +	wwn_t	lpwwn;	/* WWN of this logical port */ +}; + +/* BFA ITNIM events */ +enum bfa_itnim_aen_event { +	BFA_ITNIM_AEN_ONLINE	 = 1,	/* Target online */ +	BFA_ITNIM_AEN_OFFLINE	 = 2,	/* Target offline */ +	BFA_ITNIM_AEN_DISCONNECT = 3,	/* Target disconnected */ +}; + +struct bfa_itnim_aen_data_s { +	u16		vf_id;		/* vf_id of the IT nexus */ +	u16		rsvd[3]; +	wwn_t		ppwwn;		/* WWN of its physical port */ +	wwn_t		lpwwn;		/* WWN of logical port */ +	wwn_t		rpwwn;		/* WWN of remote(target) port */ +}; + +/* BFA audit events */ +enum bfa_audit_aen_event { +	BFA_AUDIT_AEN_AUTH_ENABLE	= 1, +	BFA_AUDIT_AEN_AUTH_DISABLE	= 2, +	BFA_AUDIT_AEN_FLASH_ERASE	= 3, +	BFA_AUDIT_AEN_FLASH_UPDATE	= 4, +}; + +struct bfa_audit_aen_data_s { +	wwn_t	pwwn; +	int	partition_inst; +	int	partition_type; +}; + +/* BFA IOC level events */ +enum bfa_ioc_aen_event { +	BFA_IOC_AEN_HBGOOD  = 1,	/* Heart Beat restore event	*/ +	BFA_IOC_AEN_HBFAIL  = 2,	/* Heart Beat failure event	*/ +	BFA_IOC_AEN_ENABLE  = 3,	/* IOC enabled event		*/ +	BFA_IOC_AEN_DISABLE = 4,	/* IOC disabled event		*/ +	BFA_IOC_AEN_FWMISMATCH  = 5,	/* IOC firmware mismatch	*/ +	BFA_IOC_AEN_FWCFG_ERROR = 6,	/* IOC firmware config error	*/ +	BFA_IOC_AEN_INVALID_VENDOR = 7, +	BFA_IOC_AEN_INVALID_NWWN = 8,	/* Zero NWWN			*/ +	BFA_IOC_AEN_INVALID_PWWN = 9	/* Zero PWWN			*/ +}; + +struct bfa_ioc_aen_data_s { +	wwn_t	pwwn; +	u16	ioc_type; +	mac_t	mac;  };  /* @@ -337,6 +565,21 @@ struct bfa_ioc_attr_s {  #define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20  #define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20  #define BFA_MFG_SUPPLIER_REVISION_SIZE		4 +/* + * Initial capability definition + */ +#define BFA_MFG_IC_FC	0x01 +#define BFA_MFG_IC_ETH	0x02 + +/* + * Adapter capability mask definition + */ +#define BFA_CM_HBA	0x01 +#define BFA_CM_CNA	0x02 +#define BFA_CM_NIC	0x04 +#define BFA_CM_FC16G	0x08 +#define BFA_CM_SRIOV	0x10 +#define BFA_CM_MEZZ	0x20  #pragma pack(1) @@ -344,31 +587,39 @@ struct bfa_ioc_attr_s {   * All numerical fields are in big-endian format.   */  struct bfa_mfg_block_s { -	u8		version;	/*  manufacturing block version */ -	u8		mfg_sig[3];	/*  characters 'M', 'F', 'G' */ -	u16	mfgsize;	/*  mfg block size */ -	u16	u16_chksum;	/*  old u16 checksum */ -	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)]; -	char		brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)]; -	u8		mfg_day;	/*  manufacturing day */ -	u8		mfg_month;	/*  manufacturing month */ -	u16	mfg_year;	/*  manufacturing year */ -	wwn_t		mfg_wwn;	/*  wwn base for this adapter */ -	u8		num_wwn;	/*  number of wwns assigned */ -	u8		mfg_speeds;	/*  speeds allowed for this adapter */ -	u8		rsv[2]; -	char		supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)]; -	char		supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)]; -	char -		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)]; -	char -		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)]; -	mac_t		mfg_mac;	/*  mac address */ -	u8		num_mac;	/*  number of mac addresses */ -	u8		rsv2; -	u32	mfg_type;	/*  card type */ -	u8		rsv3[108]; -	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*  md5 checksum */ +	u8	version;    /*!< manufacturing block version */ +	u8     mfg_sig[3]; /*!< characters 'M', 'F', 'G' */ +	u16    mfgsize;    /*!< mfg block size */ +	u16    u16_chksum; /*!< old u16 checksum */ +	char        brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)]; +	char        brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)]; +	u8     mfg_day;    /*!< manufacturing day */ +	u8     mfg_month;  /*!< manufacturing month */ +	u16    mfg_year;   /*!< manufacturing year */ +	wwn_t       mfg_wwn;    /*!< wwn base for this adapter */ +	u8     num_wwn;    /*!< number of wwns assigned */ +	u8     mfg_speeds; /*!< speeds allowed for this adapter */ +	u8     rsv[2]; +	char    supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)]; +	char    supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)]; +	char    supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)]; +	char    supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)]; +	mac_t       mfg_mac;    /*!< base mac address */ +	u8     num_mac;    /*!< number of mac addresses */ +	u8     rsv2; +	u32    card_type;  /*!< card type          */ +	char        cap_nic;    /*!< capability nic     */ +	char        cap_cna;    /*!< capability cna     */ +	char        cap_hba;    /*!< capability hba     */ +	char        cap_fc16g;  /*!< capability fc 16g      */ +	char        cap_sriov;  /*!< capability sriov       */ +	char        cap_mezz;   /*!< capability mezz        */ +	u8     rsv3; +	u8     mfg_nports; /*!< number of ports        */ +	char        media[8];   /*!< xfi/xaui           */ +	char        initial_mode[8]; /*!< initial mode: hba/cna/nic */ +	u8     rsv4[84]; +	u8     md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */  };  #pragma pack() @@ -386,17 +637,30 @@ enum {  	BFA_PCI_DEVICE_ID_FC_8G1P	= 0x17,  	BFA_PCI_DEVICE_ID_CT		= 0x14,  	BFA_PCI_DEVICE_ID_CT_FC		= 0x21, +	BFA_PCI_DEVICE_ID_CT2		= 0x22, +	BFA_PCI_DEVICE_ID_CT2_QUAD	= 0x23,  }; -#define bfa_asic_id_ct(devid)			\ -	((devid) == BFA_PCI_DEVICE_ID_CT ||	\ -	 (devid) == BFA_PCI_DEVICE_ID_CT_FC) +#define bfa_asic_id_cb(__d)			\ +	((__d) == BFA_PCI_DEVICE_ID_FC_8G2P ||	\ +	 (__d) == BFA_PCI_DEVICE_ID_FC_8G1P) +#define bfa_asic_id_ct(__d)			\ +	((__d) == BFA_PCI_DEVICE_ID_CT ||	\ +	 (__d) == BFA_PCI_DEVICE_ID_CT_FC) +#define bfa_asic_id_ct2(__d)			\ +	((__d) == BFA_PCI_DEVICE_ID_CT2 ||	\ +	(__d) == BFA_PCI_DEVICE_ID_CT2_QUAD) +#define bfa_asic_id_ctc(__d)	\ +	(bfa_asic_id_ct(__d) || bfa_asic_id_ct2(__d))  /*   * PCI sub-system device and vendor ID information   */  enum {  	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14, +	BFA_PCI_CT2_SSID_FCoE		= 0x22, +	BFA_PCI_CT2_SSID_ETH		= 0x23, +	BFA_PCI_CT2_SSID_FC		= 0x24,  };  /* @@ -416,9 +680,7 @@ enum bfa_port_speed {  	BFA_PORT_SPEED_8GBPS	= 8,  	BFA_PORT_SPEED_10GBPS	= 10,  	BFA_PORT_SPEED_16GBPS	= 16, -	BFA_PORT_SPEED_AUTO = -		(BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS | -		 BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS), +	BFA_PORT_SPEED_AUTO	= 0xf,  };  #define bfa_port_speed_t enum bfa_port_speed @@ -446,14 +708,28 @@ enum bfa_boot_bootopt {   * Boot lun information.   */  struct bfa_boot_bootlun_s { -	wwn_t   pwwn;   /*  port wwn of target */ -	lun_t   lun;    /*  64-bit lun */ +	wwn_t   pwwn;		/*  port wwn of target */ +	struct scsi_lun   lun;  /*  64-bit lun */  };  #pragma pack()  /*   * BOOT boot configuraton   */ +struct bfa_boot_cfg_s { +	u8		version; +	u8		rsvd1; +	u16		chksum; +	u8		enable;		/* enable/disable SAN boot */ +	u8		speed;          /* boot speed settings */ +	u8		topology;       /* boot topology setting */ +	u8		bootopt;        /* bfa_boot_bootopt_t */ +	u32		nbluns;         /* number of boot luns */ +	u32		rsvd2; +	struct bfa_boot_bootlun_s blun[BFA_BOOT_BOOTLUN_MAX]; +	struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX]; +}; +  struct bfa_boot_pbc_s {  	u8              enable;         /*  enable/disable SAN boot */  	u8              speed;          /*  boot speed settings */ @@ -463,4 +739,549 @@ struct bfa_boot_pbc_s {  	struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];  }; +struct bfa_ethboot_cfg_s { +	u8		version; +	u8		rsvd1; +	u16		chksum; +	u8		enable;	/* enable/disable Eth/PXE boot */ +	u8		rsvd2; +	u16		vlan; +}; + +/* + * ASIC block configuration related structures + */ +#define BFA_ABLK_MAX_PORTS	2 +#define BFA_ABLK_MAX_PFS	16 +#define BFA_ABLK_MAX		2 + +#pragma pack(1) +enum bfa_mode_s { +	BFA_MODE_HBA	= 1, +	BFA_MODE_CNA	= 2, +	BFA_MODE_NIC	= 3 +}; + +struct bfa_adapter_cfg_mode_s { +	u16	max_pf; +	u16	max_vf; +	enum bfa_mode_s	mode; +}; + +struct bfa_ablk_cfg_pf_s { +	u16	pers; +	u8	port_id; +	u8	optrom; +	u8	valid; +	u8	sriov; +	u8	max_vfs; +	u8	rsvd[1]; +	u16	num_qpairs; +	u16	num_vectors; +	u16	bw_min; +	u16	bw_max; +}; + +struct bfa_ablk_cfg_port_s { +	u8	mode; +	u8	type; +	u8	max_pfs; +	u8	rsvd[5]; +}; + +struct bfa_ablk_cfg_inst_s { +	u8	nports; +	u8	max_pfs; +	u8	rsvd[6]; +	struct bfa_ablk_cfg_pf_s	pf_cfg[BFA_ABLK_MAX_PFS]; +	struct bfa_ablk_cfg_port_s	port_cfg[BFA_ABLK_MAX_PORTS]; +}; + +struct bfa_ablk_cfg_s { +	struct bfa_ablk_cfg_inst_s	inst[BFA_ABLK_MAX]; +}; + + +/* + *	SFP module specific + */ +#define SFP_DIAGMON_SIZE	10 /* num bytes of diag monitor data */ + +/* SFP state change notification event */ +#define BFA_SFP_SCN_REMOVED	0 +#define BFA_SFP_SCN_INSERTED	1 +#define BFA_SFP_SCN_POM		2 +#define BFA_SFP_SCN_FAILED	3 +#define BFA_SFP_SCN_UNSUPPORT	4 +#define BFA_SFP_SCN_VALID	5 + +enum bfa_defs_sfp_media_e { +	BFA_SFP_MEDIA_UNKNOWN	= 0x00, +	BFA_SFP_MEDIA_CU	= 0x01, +	BFA_SFP_MEDIA_LW	= 0x02, +	BFA_SFP_MEDIA_SW	= 0x03, +	BFA_SFP_MEDIA_EL	= 0x04, +	BFA_SFP_MEDIA_UNSUPPORT	= 0x05, +}; + +/* + * values for xmtr_tech above + */ +enum { +	SFP_XMTR_TECH_CU = (1 << 0),	/* copper FC-BaseT */ +	SFP_XMTR_TECH_CP = (1 << 1),	/* copper passive */ +	SFP_XMTR_TECH_CA = (1 << 2),	/* copper active */ +	SFP_XMTR_TECH_LL = (1 << 3),	/* longwave laser */ +	SFP_XMTR_TECH_SL = (1 << 4),	/* shortwave laser w/ OFC */ +	SFP_XMTR_TECH_SN = (1 << 5),	/* shortwave laser w/o OFC */ +	SFP_XMTR_TECH_EL_INTRA = (1 << 6), /* elec intra-enclosure */ +	SFP_XMTR_TECH_EL_INTER = (1 << 7), /* elec inter-enclosure */ +	SFP_XMTR_TECH_LC = (1 << 8),	/* longwave laser */ +	SFP_XMTR_TECH_SA = (1 << 9) +}; + +/* + * Serial ID: Data Fields -- Address A0h + * Basic ID field total 64 bytes + */ +struct sfp_srlid_base_s { +	u8	id;		/* 00: Identifier */ +	u8	extid;		/* 01: Extended Identifier */ +	u8	connector;	/* 02: Connector */ +	u8	xcvr[8];	/* 03-10: Transceiver */ +	u8	encoding;	/* 11: Encoding */ +	u8	br_norm;	/* 12: BR, Nominal */ +	u8	rate_id;	/* 13: Rate Identifier */ +	u8	len_km;		/* 14: Length single mode km */ +	u8	len_100m;	/* 15: Length single mode 100m */ +	u8	len_om2;	/* 16: Length om2 fiber 10m */ +	u8	len_om1;	/* 17: Length om1 fiber 10m */ +	u8	len_cu;		/* 18: Length copper 1m */ +	u8	len_om3;	/* 19: Length om3 fiber 10m */ +	u8	vendor_name[16];/* 20-35 */ +	u8	unalloc1; +	u8	vendor_oui[3];	/* 37-39 */ +	u8	vendor_pn[16];	/* 40-55 */ +	u8	vendor_rev[4];	/* 56-59 */ +	u8	wavelen[2];	/* 60-61 */ +	u8	unalloc2; +	u8	cc_base;	/* 63: check code for base id field */ +}; + +/* + * Serial ID: Data Fields -- Address A0h + * Extended id field total 32 bytes + */ +struct sfp_srlid_ext_s { +	u8	options[2]; +	u8	br_max; +	u8	br_min; +	u8	vendor_sn[16]; +	u8	date_code[8]; +	u8	diag_mon_type;  /* 92: Diagnostic Monitoring type */ +	u8	en_options; +	u8	sff_8472; +	u8	cc_ext; +}; + +/* + * Diagnostic: Data Fields -- Address A2h + * Diagnostic and control/status base field total 96 bytes + */ +struct sfp_diag_base_s { +	/* +	 * Alarm and warning Thresholds 40 bytes +	 */ +	u8	temp_high_alarm[2]; /* 00-01 */ +	u8	temp_low_alarm[2];  /* 02-03 */ +	u8	temp_high_warning[2];   /* 04-05 */ +	u8	temp_low_warning[2];    /* 06-07 */ + +	u8	volt_high_alarm[2]; /* 08-09 */ +	u8	volt_low_alarm[2];  /* 10-11 */ +	u8	volt_high_warning[2];   /* 12-13 */ +	u8	volt_low_warning[2];    /* 14-15 */ + +	u8	bias_high_alarm[2]; /* 16-17 */ +	u8	bias_low_alarm[2];  /* 18-19 */ +	u8	bias_high_warning[2];   /* 20-21 */ +	u8	bias_low_warning[2];    /* 22-23 */ + +	u8	tx_pwr_high_alarm[2];   /* 24-25 */ +	u8	tx_pwr_low_alarm[2];    /* 26-27 */ +	u8	tx_pwr_high_warning[2]; /* 28-29 */ +	u8	tx_pwr_low_warning[2];  /* 30-31 */ + +	u8	rx_pwr_high_alarm[2];   /* 32-33 */ +	u8	rx_pwr_low_alarm[2];    /* 34-35 */ +	u8	rx_pwr_high_warning[2]; /* 36-37 */ +	u8	rx_pwr_low_warning[2];  /* 38-39 */ + +	u8	unallocate_1[16]; + +	/* +	 * ext_cal_const[36] +	 */ +	u8	rx_pwr[20]; +	u8	tx_i[4]; +	u8	tx_pwr[4]; +	u8	temp[4]; +	u8	volt[4]; +	u8	unallocate_2[3]; +	u8	cc_dmi; +}; + +/* + * Diagnostic: Data Fields -- Address A2h + * Diagnostic and control/status extended field total 24 bytes + */ +struct sfp_diag_ext_s { +	u8	diag[SFP_DIAGMON_SIZE]; +	u8	unalloc1[4]; +	u8	status_ctl; +	u8	rsvd; +	u8	alarm_flags[2]; +	u8	unalloc2[2]; +	u8	warning_flags[2]; +	u8	ext_status_ctl[2]; +}; + +/* + * Diagnostic: Data Fields -- Address A2h + * General Use Fields: User Writable Table - Features's Control Registers + * Total 32 bytes + */ +struct sfp_usr_eeprom_s { +	u8	rsvd1[2];       /* 128-129 */ +	u8	ewrap;          /* 130 */ +	u8	rsvd2[2];       /*  */ +	u8	owrap;          /* 133 */ +	u8	rsvd3[2];       /*  */ +	u8	prbs;           /* 136: PRBS 7 generator */ +	u8	rsvd4[2];       /*  */ +	u8	tx_eqz_16;      /* 139: TX Equalizer (16xFC) */ +	u8	tx_eqz_8;       /* 140: TX Equalizer (8xFC) */ +	u8	rsvd5[2];       /*  */ +	u8	rx_emp_16;      /* 143: RX Emphasis (16xFC) */ +	u8	rx_emp_8;       /* 144: RX Emphasis (8xFC) */ +	u8	rsvd6[2];       /*  */ +	u8	tx_eye_adj;     /* 147: TX eye Threshold Adjust */ +	u8	rsvd7[3];       /*  */ +	u8	tx_eye_qctl;    /* 151: TX eye Quality Control */ +	u8	tx_eye_qres;    /* 152: TX eye Quality Result */ +	u8	rsvd8[2];       /*  */ +	u8	poh[3];         /* 155-157: Power On Hours */ +	u8	rsvd9[2];       /*  */ +}; + +struct sfp_mem_s { +	struct sfp_srlid_base_s	srlid_base; +	struct sfp_srlid_ext_s	srlid_ext; +	struct sfp_diag_base_s	diag_base; +	struct sfp_diag_ext_s	diag_ext; +	struct sfp_usr_eeprom_s usr_eeprom; +}; + +/* + * transceiver codes (SFF-8472 Rev 10.2 Table 3.5) + */ +union sfp_xcvr_e10g_code_u { +	u8		b; +	struct { +#ifdef __BIG_ENDIAN +		u8	e10g_unall:1;   /* 10G Ethernet compliance */ +		u8	e10g_lrm:1; +		u8	e10g_lr:1; +		u8	e10g_sr:1; +		u8	ib_sx:1;    /* Infiniband compliance */ +		u8	ib_lx:1; +		u8	ib_cu_a:1; +		u8	ib_cu_p:1; +#else +		u8	ib_cu_p:1; +		u8	ib_cu_a:1; +		u8	ib_lx:1; +		u8	ib_sx:1;    /* Infiniband compliance */ +		u8	e10g_sr:1; +		u8	e10g_lr:1; +		u8	e10g_lrm:1; +		u8	e10g_unall:1;   /* 10G Ethernet compliance */ +#endif +	} r; +}; + +union sfp_xcvr_so1_code_u { +	u8		b; +	struct { +		u8	escon:2;    /* ESCON compliance code */ +		u8	oc192_reach:1;  /* SONET compliance code */ +		u8	so_reach:2; +		u8	oc48_reach:3; +	} r; +}; + +union sfp_xcvr_so2_code_u { +	u8		b; +	struct { +		u8	reserved:1; +		u8	oc12_reach:3;   /* OC12 reach */ +		u8	reserved1:1; +		u8	oc3_reach:3;    /* OC3 reach */ +	} r; +}; + +union sfp_xcvr_eth_code_u { +	u8		b; +	struct { +		u8	base_px:1; +		u8	base_bx10:1; +		u8	e100base_fx:1; +		u8	e100base_lx:1; +		u8	e1000base_t:1; +		u8	e1000base_cx:1; +		u8	e1000base_lx:1; +		u8	e1000base_sx:1; +	} r; +}; + +struct sfp_xcvr_fc1_code_s { +	u8	link_len:5; /* FC link length */ +	u8	xmtr_tech2:3; +	u8	xmtr_tech1:7;   /* FC transmitter technology */ +	u8	reserved1:1; +}; + +union sfp_xcvr_fc2_code_u { +	u8		b; +	struct { +		u8	tw_media:1; /* twin axial pair (tw) */ +		u8	tp_media:1; /* shielded twisted pair (sp) */ +		u8	mi_media:1; /* miniature coax (mi) */ +		u8	tv_media:1; /* video coax (tv) */ +		u8	m6_media:1; /* multimode, 62.5m (m6) */ +		u8	m5_media:1; /* multimode, 50m (m5) */ +		u8	reserved:1; +		u8	sm_media:1; /* single mode (sm) */ +	} r; +}; + +union sfp_xcvr_fc3_code_u { +	u8		b; +	struct { +#ifdef __BIG_ENDIAN +		u8	rsv4:1; +		u8	mb800:1;    /* 800 Mbytes/sec */ +		u8	mb1600:1;   /* 1600 Mbytes/sec */ +		u8	mb400:1;    /* 400 Mbytes/sec */ +		u8	rsv2:1; +		u8	mb200:1;    /* 200 Mbytes/sec */ +		u8	rsv1:1; +		u8	mb100:1;    /* 100 Mbytes/sec */ +#else +		u8	mb100:1;    /* 100 Mbytes/sec */ +		u8	rsv1:1; +		u8	mb200:1;    /* 200 Mbytes/sec */ +		u8	rsv2:1; +		u8	mb400:1;    /* 400 Mbytes/sec */ +		u8	mb1600:1;   /* 1600 Mbytes/sec */ +		u8	mb800:1;    /* 800 Mbytes/sec */ +		u8	rsv4:1; +#endif +	} r; +}; + +struct sfp_xcvr_s { +	union sfp_xcvr_e10g_code_u	e10g; +	union sfp_xcvr_so1_code_u	so1; +	union sfp_xcvr_so2_code_u	so2; +	union sfp_xcvr_eth_code_u	eth; +	struct sfp_xcvr_fc1_code_s	fc1; +	union sfp_xcvr_fc2_code_u	fc2; +	union sfp_xcvr_fc3_code_u	fc3; +}; + +/* + *	Flash module specific + */ +#define BFA_FLASH_PART_ENTRY_SIZE	32	/* partition entry size */ +#define BFA_FLASH_PART_MAX		32	/* maximal # of partitions */ + +enum bfa_flash_part_type { +	BFA_FLASH_PART_OPTROM   = 1,    /* option rom partition */ +	BFA_FLASH_PART_FWIMG    = 2,    /* firmware image partition */ +	BFA_FLASH_PART_FWCFG    = 3,    /* firmware tuneable config */ +	BFA_FLASH_PART_DRV      = 4,    /* IOC driver config */ +	BFA_FLASH_PART_BOOT     = 5,    /* boot config */ +	BFA_FLASH_PART_ASIC     = 6,    /* asic bootstrap configuration */ +	BFA_FLASH_PART_MFG      = 7,    /* manufacturing block partition */ +	BFA_FLASH_PART_OPTROM2  = 8,    /* 2nd option rom partition */ +	BFA_FLASH_PART_VPD      = 9,    /* vpd data of OEM info */ +	BFA_FLASH_PART_PBC      = 10,   /* pre-boot config */ +	BFA_FLASH_PART_BOOTOVL  = 11,   /* boot overlay partition */ +	BFA_FLASH_PART_LOG      = 12,   /* firmware log partition */ +	BFA_FLASH_PART_PXECFG   = 13,   /* pxe boot config partition */ +	BFA_FLASH_PART_PXEOVL   = 14,   /* pxe boot overlay partition */ +	BFA_FLASH_PART_PORTCFG  = 15,   /* port cfg partition */ +	BFA_FLASH_PART_ASICBK   = 16,   /* asic backup partition */ +}; + +/* + * flash partition attributes + */ +struct bfa_flash_part_attr_s { +	u32	part_type;      /* partition type */ +	u32	part_instance;  /* partition instance */ +	u32	part_off;       /* partition offset */ +	u32	part_size;      /* partition size */ +	u32	part_len;       /* partition content length */ +	u32	part_status;    /* partition status */ +	char	rsv[BFA_FLASH_PART_ENTRY_SIZE - 24]; +}; + +/* + * flash attributes + */ +struct bfa_flash_attr_s { +	u32	status; /* flash overall status */ +	u32	npart;  /* num of partitions */ +	struct bfa_flash_part_attr_s part[BFA_FLASH_PART_MAX]; +}; + +/* + *	DIAG module specific + */ +#define LB_PATTERN_DEFAULT	0xB5B5B5B5 +#define QTEST_CNT_DEFAULT	10 +#define QTEST_PAT_DEFAULT	LB_PATTERN_DEFAULT +#define DPORT_ENABLE_LOOPCNT_DEFAULT (1024 * 1024) + +struct bfa_diag_memtest_s { +	u8	algo; +	u8	rsvd[7]; +}; + +struct bfa_diag_memtest_result { +	u32	status; +	u32	addr; +	u32	exp; /* expect value read from reg */ +	u32	act; /* actually value read */ +	u32	err_status;             /* error status reg */ +	u32	err_status1;    /* extra error info reg */ +	u32	err_addr; /* error address reg */ +	u8	algo; +	u8	rsv[3]; +}; + +struct bfa_diag_loopback_result_s { +	u32	numtxmfrm;      /* no. of transmit frame */ +	u32	numosffrm;      /* no. of outstanding frame */ +	u32	numrcvfrm;      /* no. of received good frame */ +	u32	badfrminf;      /* mis-match info */ +	u32	badfrmnum;      /* mis-match fram number */ +	u8	status;         /* loopback test result */ +	u8	rsvd[3]; +}; + +enum bfa_diag_dport_test_status { +	DPORT_TEST_ST_IDLE	= 0,    /* the test has not started yet. */ +	DPORT_TEST_ST_FINAL	= 1,    /* the test done successfully */ +	DPORT_TEST_ST_SKIP	= 2,    /* the test skipped */ +	DPORT_TEST_ST_FAIL	= 3,    /* the test failed */ +	DPORT_TEST_ST_INPRG	= 4,    /* the testing is in progress */ +	DPORT_TEST_ST_RESPONDER	= 5,    /* test triggered from remote port */ +	DPORT_TEST_ST_STOPPED	= 6,    /* the test stopped by user. */ +	DPORT_TEST_ST_MAX +}; + +enum bfa_diag_dport_test_type { +	DPORT_TEST_ELOOP	= 0, +	DPORT_TEST_OLOOP	= 1, +	DPORT_TEST_ROLOOP	= 2, +	DPORT_TEST_LINK		= 3, +	DPORT_TEST_MAX +}; + +enum bfa_diag_dport_test_opmode { +	BFA_DPORT_OPMODE_AUTO	= 0, +	BFA_DPORT_OPMODE_MANU	= 1, +}; + +struct bfa_diag_dport_subtest_result_s { +	u8	status;		/* bfa_diag_dport_test_status */ +	u8	rsvd[7];	/* 64bit align */ +	u64	start_time;	/* timestamp  */ +}; + +struct bfa_diag_dport_result_s { +	wwn_t	rp_pwwn;	/* switch port wwn  */ +	wwn_t	rp_nwwn;	/* switch node wwn  */ +	u64	start_time;	/* user/sw start time */ +	u64	end_time;	/* timestamp  */ +	u8	status;		/* bfa_diag_dport_test_status */ +	u8	mode;		/* bfa_diag_dport_test_opmode */ +	u8	rsvd;		/* 64bit align */ +	u8	speed;		/* link speed for buf_reqd */ +	u16	buffer_required; +	u16	frmsz;		/* frame size for buf_reqd */ +	u32	lpcnt;		/* Frame count */ +	u32	pat;		/* Pattern */ +	u32	roundtrip_latency;	/* in nano sec */ +	u32	est_cable_distance;	/* in meter */ +	struct bfa_diag_dport_subtest_result_s subtest[DPORT_TEST_MAX]; +}; + +struct bfa_diag_ledtest_s { +	u32	cmd;    /* bfa_led_op_t */ +	u32	color;  /* bfa_led_color_t */ +	u16	freq;   /* no. of blinks every 10 secs */ +	u8	led;    /* bitmap of LEDs to be tested */ +	u8	rsvd[5]; +}; + +struct bfa_diag_loopback_s { +	u32	loopcnt; +	u32	pattern; +	u8	lb_mode;    /* bfa_port_opmode_t */ +	u8	speed;      /* bfa_port_speed_t */ +	u8	rsvd[2]; +}; + +/* + *	PHY module specific + */ +enum bfa_phy_status_e { +	BFA_PHY_STATUS_GOOD	= 0, /* phy is good */ +	BFA_PHY_STATUS_NOT_PRESENT	= 1, /* phy does not exist */ +	BFA_PHY_STATUS_BAD	= 2, /* phy is bad */ +}; + +/* + * phy attributes for phy query + */ +struct bfa_phy_attr_s { +	u32	status;         /* phy present/absent status */ +	u32	length;         /* firmware length */ +	u32	fw_ver;         /* firmware version */ +	u32	an_status;      /* AN status */ +	u32	pma_pmd_status; /* PMA/PMD link status */ +	u32	pma_pmd_signal; /* PMA/PMD signal detect */ +	u32	pcs_status;     /* PCS link status */ +}; + +/* + * phy stats + */ +struct bfa_phy_stats_s { +	u32	status;         /* phy stats status */ +	u32	link_breaks;    /* Num of link breaks after linkup */ +	u32	pma_pmd_fault;  /* NPMA/PMD fault */ +	u32	pcs_fault;      /* PCS fault */ +	u32	speed_neg;      /* Num of speed negotiation */ +	u32	tx_eq_training; /* Num of TX EQ training */ +	u32	tx_eq_timeout;  /* Num of TX EQ timeout */ +	u32	crc_error;      /* Num of CRC errors */ +}; + +#pragma pack() +  #endif /* __BFA_DEFS_H__ */ diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h index 191d34a58b9..06f0a163ca3 100644 --- a/drivers/scsi/bfa/bfa_defs_fcs.h +++ b/drivers/scsi/bfa/bfa_defs_fcs.h @@ -90,12 +90,15 @@ enum bfa_lport_role {   * FCS port configuration.   */  struct bfa_lport_cfg_s { -    wwn_t	       pwwn;       /*  port wwn */ -    wwn_t	       nwwn;       /*  node wwn */ -    struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */ -    bfa_boolean_t       preboot_vp;  /*  vport created from PBC */ -    enum bfa_lport_role     roles;      /*  FCS port roles */ -    u8	     tag[16];	/*  opaque tag from application */ +	wwn_t	       pwwn;       /*  port wwn */ +	wwn_t	       nwwn;       /*  node wwn */ +	struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */ +	struct bfa_lport_symname_s node_sym_name; /* Node symbolic name */ +	enum bfa_lport_role roles;      /* FCS port roles */ +	u32     rsvd; +	bfa_boolean_t   preboot_vp;  /*  vport created from PBC */ +	u8	tag[16];        /* opaque tag from application */ +	u8	padding[4];  };  /* @@ -190,6 +193,18 @@ struct bfa_lport_stats_s {  	u32	ns_gidft_unknown_rsp;  	u32	ns_gidft_alloc_wait; +	u32	ns_rnnid_sent; +	u32	ns_rnnid_accepts; +	u32	ns_rnnid_rsp_err; +	u32	ns_rnnid_rejects; +	u32	ns_rnnid_alloc_wait; + +	u32	ns_rsnn_nn_sent; +	u32	ns_rsnn_nn_accepts; +	u32	ns_rsnn_nn_rsp_err; +	u32	ns_rsnn_nn_rejects; +	u32	ns_rsnn_nn_alloc_wait; +  	/*  	 * Mgmt Server stats  	 */ @@ -249,12 +264,13 @@ enum bfa_vport_state {  	BFA_FCS_VPORT_FDISC_SEND	= 2,  	BFA_FCS_VPORT_FDISC		= 3,  	BFA_FCS_VPORT_FDISC_RETRY	= 4, -	BFA_FCS_VPORT_ONLINE		= 5, -	BFA_FCS_VPORT_DELETING		= 6, -	BFA_FCS_VPORT_CLEANUP		= 6, -	BFA_FCS_VPORT_LOGO_SEND		= 7, -	BFA_FCS_VPORT_LOGO		= 8, -	BFA_FCS_VPORT_ERROR		= 9, +	BFA_FCS_VPORT_FDISC_RSP_WAIT	= 5, +	BFA_FCS_VPORT_ONLINE		= 6, +	BFA_FCS_VPORT_DELETING		= 7, +	BFA_FCS_VPORT_CLEANUP		= 8, +	BFA_FCS_VPORT_LOGO_SEND		= 9, +	BFA_FCS_VPORT_LOGO		= 10, +	BFA_FCS_VPORT_ERROR		= 11,  	BFA_FCS_VPORT_MAX_STATE,  }; @@ -407,6 +423,11 @@ struct bfa_rport_remote_link_stats_s {  	u32 icc; /*  Invalid CRC Count */  }; +struct bfa_rport_qualifier_s { +	wwn_t	pwwn;	/* Port WWN */ +	u32	pid;	/* port ID */ +	u32	rsvd; +};  #define BFA_MAX_IO_INDEX 7  #define BFA_NO_IO_INDEX 9 diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index e24e9f7ca81..638f441ffc3 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -34,40 +34,43 @@  struct bfa_iocfc_intr_attr_s {  	u8		coalesce;	/*  enable/disable coalescing */  	u8		rsvd[3]; -	u16	latency;	/*  latency in microseconds   */ -	u16	delay;		/*  delay in microseconds     */ +	__be16		latency;	/*  latency in microseconds   */ +	__be16		delay;		/*  delay in microseconds     */  };  /*   * IOC firmware configuraton   */  struct bfa_iocfc_fwcfg_s { -	u16        num_fabrics;	/*  number of fabrics		*/ -	u16        num_lports;	/*  number of local lports	*/ -	u16        num_rports;	/*  number of remote ports	*/ -	u16        num_ioim_reqs;	/*  number of IO reqs		*/ -	u16        num_tskim_reqs;	/*  task management requests	*/ -	u16        num_iotm_reqs;	/*  number of TM IO reqs	*/ -	u16        num_tsktm_reqs;	/*  TM task management requests*/ -	u16        num_fcxp_reqs;	/*  unassisted FC exchanges	*/ -	u16        num_uf_bufs;	/*  unsolicited recv buffers	*/ +	u16		num_fabrics;	/*  number of fabrics		*/ +	u16		num_lports;	/*  number of local lports	*/ +	u16		num_rports;	/*  number of remote ports	*/ +	u16		num_ioim_reqs;	/*  number of IO reqs		*/ +	u16		num_tskim_reqs;	/*  task management requests	*/ +	u16		num_fwtio_reqs;	/* number of TM IO reqs in FW   */ +	u16		num_fcxp_reqs;	/*  unassisted FC exchanges	*/ +	u16		num_uf_bufs;	/*  unsolicited recv buffers	*/  	u8		num_cqs;  	u8		fw_tick_res;	/*  FW clock resolution in ms */ -	u8		rsvd[4]; +	u8		rsvd[6];  };  #pragma pack()  struct bfa_iocfc_drvcfg_s { -	u16        num_reqq_elems;	/*  number of req queue elements */ -	u16        num_rspq_elems;	/*  number of rsp queue elements */ -	u16        num_sgpgs;	/*  number of total SG pages	  */ -	u16        num_sboot_tgts;	/*  number of SAN boot targets	  */ -	u16        num_sboot_luns;	/*  number of SAN boot luns	  */ -	u16	    ioc_recover;	/*  IOC recovery mode		  */ -	u16	    min_cfg;	/*  minimum configuration	  */ -	u16        path_tov;	/*  device path timeout	  */ -	bfa_boolean_t   delay_comp; /*  delay completion of -							failed inflight IOs */ +	u16		num_reqq_elems;	/*  number of req queue elements */ +	u16		num_rspq_elems;	/*  number of rsp queue elements */ +	u16		num_sgpgs;	/*  number of total SG pages	 */ +	u16		num_sboot_tgts;	/*  number of SAN boot targets	 */ +	u16		num_sboot_luns;	/*  number of SAN boot luns	 */ +	u16		ioc_recover;	/*  IOC recovery mode		 */ +	u16		min_cfg;	/*  minimum configuration	 */ +	u16		path_tov;	/*  device path timeout		*/ +	u16		num_tio_reqs;	/* number of TM IO reqs	*/ +	u8		port_mode; +	u8		rsvd_a; +	bfa_boolean_t	delay_comp;	/* delay completion of failed +					 * inflight IOs */ +	u16		num_ttsk_reqs;	 /* TM task management requests */  	u32		rsvd;  }; @@ -82,7 +85,7 @@ struct bfa_iocfc_cfg_s {  /*   * IOC firmware IO stats   */ -struct bfa_fw_io_stats_s { +struct bfa_fw_ioim_stats_s {  	u32	host_abort;		/*  IO aborted by host driver*/  	u32	host_cleanup;		/*  IO clean up by host driver */ @@ -98,10 +101,13 @@ struct bfa_fw_io_stats_s {  	u32	fw_frm_drop;		/*  f/w drop the frame */  	u32	rec_timeout;		/*  FW rec timed out */ -	u32	error_rec;			/*  FW sending rec on -							* an error condition*/ +	u32	error_rec;		/*  FW sending rec on +					 *  an error condition*/  	u32	wait_for_si;		/*  FW wait for SI */  	u32	rec_rsp_inval;		/*  REC rsp invalid */ +	u32     rec_rsp_xchg_comp;	/*  REC rsp xchg complete */ +	u32     rec_rsp_rd_si_ownd;	/*  REC rsp read si owned */ +  	u32	seqr_io_abort;		/*  target does not know cmd so abort */  	u32	seqr_io_retry;		/*  SEQR failed so retry IO */ @@ -121,9 +127,9 @@ struct bfa_fw_io_stats_s {  	u32	unexp_fcp_rsp;		/*  fcp response in wrong state */  	u32	fcp_rsp_under_run;	/*  fcp rsp IO underrun */ -	u32        fcp_rsp_under_run_wr;   /*  fcp rsp IO underrun for write */ +	u32     fcp_rsp_under_run_wr;   /*  fcp rsp IO underrun for write */  	u32	fcp_rsp_under_run_err;	/*  fcp rsp IO underrun error */ -	u32        fcp_rsp_resid_inval;    /*  invalid residue */ +	u32     fcp_rsp_resid_inval;    /*  invalid residue */  	u32	fcp_rsp_over_run;	/*  fcp rsp IO overrun */  	u32	fcp_rsp_over_run_err;	/*  fcp rsp IO overrun error */  	u32	fcp_rsp_proto_err;	/*  protocol error in fcp rsp */ @@ -139,17 +145,66 @@ struct bfa_fw_io_stats_s {  	u32	ioh_hit_class2_event;	/*  IOH hit class2 */  	u32	ioh_miss_other_event;	/*  IOH miss other */  	u32	ioh_seq_cnt_err_event;	/*  IOH seq cnt error */ -	u32	ioh_len_err_event;		/*  IOH len error - fcp_dl != -							* bytes xfered */ +	u32	ioh_len_err_event;	/*  IOH len error - fcp_dl != +					 *  bytes xfered */  	u32	ioh_seq_len_err_event;	/*  IOH seq len error */  	u32	ioh_data_oor_event;	/*  Data out of range */  	u32	ioh_ro_ooo_event;	/*  Relative offset out of range */  	u32	ioh_cpu_owned_event;	/*  IOH hit -iost owned by f/w */ -	u32	ioh_unexp_frame_event;	/*  unexpected frame recieved -						 *   count */ +	u32	ioh_unexp_frame_event;	/*  unexpected frame received +					 *  count */  	u32	ioh_err_int;		/*  IOH error int during data-phase -						 *   for scsi write -						 */ +					 *  for scsi write */ +}; + +struct bfa_fw_tio_stats_s { +	u32	tio_conf_proc;	    /* TIO CONF processed */ +	u32	tio_conf_drop;      /* TIO CONF dropped */ +	u32	tio_cleanup_req;    /* TIO cleanup requested */ +	u32	tio_cleanup_comp;   /* TIO cleanup completed */ +	u32	tio_abort_rsp;      /* TIO abort response */ +	u32	tio_abort_rsp_comp; /* TIO abort rsp completed */ +	u32	tio_abts_req;       /* TIO ABTS requested */ +	u32	tio_abts_ack;       /* TIO ABTS ack-ed */ +	u32	tio_abts_ack_nocomp;/* TIO ABTS ack-ed but not completed */ +	u32	tio_abts_tmo;       /* TIO ABTS timeout */ +	u32	tio_snsdata_dma;    /* TIO sense data DMA */ +	u32	tio_rxwchan_wait;   /* TIO waiting for RX wait channel */ +	u32	tio_rxwchan_avail;  /* TIO RX wait channel available */ +	u32	tio_hit_bls;        /* TIO IOH BLS event */ +	u32	tio_uf_recv;        /* TIO received UF */ +	u32	tio_rd_invalid_sm;  /* TIO read reqst in wrong state machine */ +	u32	tio_wr_invalid_sm;  /* TIO write reqst in wrong state machine */ + +	u32	ds_rxwchan_wait;    /* DS waiting for RX wait channel */ +	u32	ds_rxwchan_avail;   /* DS RX wait channel available */ +	u32	ds_unaligned_rd;    /* DS unaligned read */ +	u32	ds_rdcomp_invalid_sm; /* DS read completed in wrong state +				       * machine */ +	u32	ds_wrcomp_invalid_sm; /* DS write completed in wrong state +				       * machine */ +	u32	ds_flush_req;       /* DS flush requested */ +	u32	ds_flush_comp;      /* DS flush completed */ +	u32	ds_xfrdy_exp;       /* DS XFER_RDY expired */ +	u32	ds_seq_cnt_err;     /* DS seq cnt error */ +	u32	ds_seq_len_err;     /* DS seq len error */ +	u32	ds_data_oor;        /* DS data out of order */ +	u32	ds_hit_bls;	    /* DS hit BLS */ +	u32	ds_edtov_timer_exp; /* DS edtov expired */ +	u32	ds_cpu_owned;       /* DS cpu owned */ +	u32	ds_hit_class2;      /* DS hit class2 */ +	u32	ds_length_err;      /* DS length error */ +	u32	ds_ro_ooo_err;      /* DS relative offset out-of-order error */ +	u32	ds_rectov_timer_exp;/* DS rectov expired */ +	u32	ds_unexp_fr_err;    /* DS unexp frame error */ +}; + +/* + * IOC firmware IO stats + */ +struct bfa_fw_io_stats_s { +	struct bfa_fw_ioim_stats_s	ioim_stats; +	struct bfa_fw_tio_stats_s	tio_stats;  };  /* @@ -157,117 +212,154 @@ struct bfa_fw_io_stats_s {   */  struct bfa_fw_port_fpg_stats_s { -    u32    intr_evt; -    u32    intr; -    u32    intr_excess; -    u32    intr_cause0; -    u32    intr_other; -    u32    intr_other_ign; -    u32    sig_lost; -    u32    sig_regained; -    u32    sync_lost; -    u32    sync_to; -    u32    sync_regained; -    u32    div2_overflow; -    u32    div2_underflow; -    u32    efifo_overflow; -    u32    efifo_underflow; -    u32    idle_rx; -    u32    lrr_rx; -    u32    lr_rx; -    u32    ols_rx; -    u32    nos_rx; -    u32    lip_rx; -    u32    arbf0_rx; -    u32    arb_rx; -    u32    mrk_rx; -    u32    const_mrk_rx; -    u32    prim_unknown; +	u32    intr_evt; +	u32    intr; +	u32    intr_excess; +	u32    intr_cause0; +	u32    intr_other; +	u32    intr_other_ign; +	u32    sig_lost; +	u32    sig_regained; +	u32    sync_lost; +	u32    sync_to; +	u32    sync_regained; +	u32    div2_overflow; +	u32    div2_underflow; +	u32    efifo_overflow; +	u32    efifo_underflow; +	u32    idle_rx; +	u32    lrr_rx; +	u32    lr_rx; +	u32    ols_rx; +	u32    nos_rx; +	u32    lip_rx; +	u32    arbf0_rx; +	u32    arb_rx; +	u32    mrk_rx; +	u32    const_mrk_rx; +	u32    prim_unknown;  };  struct bfa_fw_port_lksm_stats_s { -    u32    hwsm_success;       /*  hwsm state machine success          */ -    u32    hwsm_fails;         /*  hwsm fails                          */ -    u32    hwsm_wdtov;         /*  hwsm timed out                      */ -    u32    swsm_success;       /*  swsm success                        */ -    u32    swsm_fails;         /*  swsm fails                          */ -    u32    swsm_wdtov;         /*  swsm timed out                      */ -    u32    busybufs;           /*  link init failed due to busybuf     */ -    u32    buf_waits;          /*  bufwait state entries               */ -    u32    link_fails;         /*  link failures                       */ -    u32    psp_errors;         /*  primitive sequence protocol errors  */ -    u32    lr_unexp;           /*  No. of times LR rx-ed unexpectedly  */ -    u32    lrr_unexp;          /*  No. of times LRR rx-ed unexpectedly */ -    u32    lr_tx;              /*  No. of times LR tx started          */ -    u32    lrr_tx;             /*  No. of times LRR tx started         */ -    u32    ols_tx;             /*  No. of times OLS tx started         */ -    u32    nos_tx;             /*  No. of times NOS tx started         */ -    u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */ -    u32    hwsm_lr_rx;         /*  No. of times LR rx-ed by HWSM      */ +	u32    hwsm_success;       /*  hwsm state machine success          */ +	u32    hwsm_fails;         /*  hwsm fails                          */ +	u32    hwsm_wdtov;         /*  hwsm timed out                      */ +	u32    swsm_success;       /*  swsm success                        */ +	u32    swsm_fails;         /*  swsm fails                          */ +	u32    swsm_wdtov;         /*  swsm timed out                      */ +	u32    busybufs;           /*  link init failed due to busybuf     */ +	u32    buf_waits;          /*  bufwait state entries               */ +	u32    link_fails;         /*  link failures                       */ +	u32    psp_errors;         /*  primitive sequence protocol errors  */ +	u32    lr_unexp;           /*  No. of times LR rx-ed unexpectedly  */ +	u32    lrr_unexp;          /*  No. of times LRR rx-ed unexpectedly */ +	u32    lr_tx;              /*  No. of times LR tx started          */ +	u32    lrr_tx;             /*  No. of times LRR tx started         */ +	u32    ols_tx;             /*  No. of times OLS tx started         */ +	u32    nos_tx;             /*  No. of times NOS tx started         */ +	u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */ +	u32    hwsm_lr_rx;         /*  No. of times LR rx-ed by HWSM       */  };  struct bfa_fw_port_snsm_stats_s { -    u32    hwsm_success;       /*  Successful hwsm terminations        */ -    u32    hwsm_fails;         /*  hwsm fail count                     */ -    u32    hwsm_wdtov;         /*  hwsm timed out                      */ -    u32    swsm_success;       /*  swsm success                        */ -    u32    swsm_wdtov;         /*  swsm timed out                      */ -    u32    error_resets;       /*  error resets initiated by upsm      */ -    u32    sync_lost;          /*  Sync loss count                     */ -    u32    sig_lost;           /*  Signal loss count                   */ +	u32    hwsm_success;       /*  Successful hwsm terminations        */ +	u32    hwsm_fails;         /*  hwsm fail count                     */ +	u32    hwsm_wdtov;         /*  hwsm timed out                      */ +	u32    swsm_success;       /*  swsm success                        */ +	u32    swsm_wdtov;         /*  swsm timed out                      */ +	u32    error_resets;       /*  error resets initiated by upsm      */ +	u32    sync_lost;          /*  Sync loss count                     */ +	u32    sig_lost;           /*  Signal loss count                   */ +	u32    asn8g_attempts;	   /* SNSM HWSM at 8Gbps attempts	   */ +	u32    adapt_success;	   /* SNSM adaptation success	*/ +	u32    adapt_fails;	   /* SNSM adaptation failures */ +	u32    adapt_ign_fails;	   /* SNSM adaptation failures ignored */  };  struct bfa_fw_port_physm_stats_s { -    u32    module_inserts;     /*  Module insert count                 */ -    u32    module_xtracts;     /*  Module extracts count               */ -    u32    module_invalids;    /*  Invalid module inserted count       */ -    u32    module_read_ign;    /*  Module validation status ignored    */ -    u32    laser_faults;       /*  Laser fault count                   */ -    u32    rsvd; +	u32    module_inserts;     /*  Module insert count                 */ +	u32    module_xtracts;     /*  Module extracts count               */ +	u32    module_invalids;    /*  Invalid module inserted count       */ +	u32    module_read_ign;    /*  Module validation status ignored    */ +	u32    laser_faults;       /*  Laser fault count                   */ +	u32    rsvd;  };  struct bfa_fw_fip_stats_s { -    u32    vlan_req;           /*  vlan discovery requests             */ -    u32    vlan_notify;        /*  vlan notifications                  */ -    u32    vlan_err;           /*  vlan response error                 */ -    u32    vlan_timeouts;      /*  vlan disvoery timeouts              */ -    u32    vlan_invalids;      /*  invalid vlan in discovery advert.   */ -    u32    disc_req;           /*  Discovery solicit requests          */ -    u32    disc_rsp;           /*  Discovery solicit response          */ -    u32    disc_err;           /*  Discovery advt. parse errors        */ -    u32    disc_unsol;         /*  Discovery unsolicited               */ -    u32    disc_timeouts;      /*  Discovery timeouts                  */ -    u32    disc_fcf_unavail;   /*  Discovery FCF Not Avail.            */ -    u32    linksvc_unsupp;     /*  Unsupported link service req        */ -    u32    linksvc_err;        /*  Parse error in link service req     */ -    u32    logo_req;           /*  FIP logos received                  */ -    u32    clrvlink_req;       /*  Clear virtual link req              */ -    u32    op_unsupp;          /*  Unsupported FIP operation           */ -    u32    untagged;           /*  Untagged frames (ignored)           */ -    u32    invalid_version;    /*  Invalid FIP version                 */ +	u32    vlan_req;           /*  vlan discovery requests             */ +	u32    vlan_notify;        /*  vlan notifications                  */ +	u32    vlan_err;           /*  vlan response error                 */ +	u32    vlan_timeouts;      /*  vlan disvoery timeouts              */ +	u32    vlan_invalids;      /*  invalid vlan in discovery advert.   */ +	u32    disc_req;           /*  Discovery solicit requests          */ +	u32    disc_rsp;           /*  Discovery solicit response          */ +	u32    disc_err;           /*  Discovery advt. parse errors        */ +	u32    disc_unsol;         /*  Discovery unsolicited               */ +	u32    disc_timeouts;      /*  Discovery timeouts                  */ +	u32    disc_fcf_unavail;   /*  Discovery FCF Not Avail.            */ +	u32    linksvc_unsupp;     /*  Unsupported link service req        */ +	u32    linksvc_err;        /*  Parse error in link service req     */ +	u32    logo_req;           /*  FIP logos received                  */ +	u32    clrvlink_req;       /*  Clear virtual link req              */ +	u32    op_unsupp;          /*  Unsupported FIP operation           */ +	u32    untagged;           /*  Untagged frames (ignored)           */ +	u32    invalid_version;    /*  Invalid FIP version                 */  };  struct bfa_fw_lps_stats_s { -    u32    mac_invalids;       /*  Invalid mac assigned                */ -    u32    rsvd; +	u32    mac_invalids;       /*  Invalid mac assigned                */ +	u32    rsvd;  };  struct bfa_fw_fcoe_stats_s { -    u32    cee_linkups;        /*  CEE link up count                   */ -    u32    cee_linkdns;        /*  CEE link down count                 */ -    u32    fip_linkups;        /*  FIP link up count                   */ -    u32    fip_linkdns;        /*  FIP link up count                   */ -    u32    fip_fails;          /*  FIP fail count                      */ -    u32    mac_invalids;       /*  Invalid mac assigned                */ +	u32    cee_linkups;        /*  CEE link up count                   */ +	u32    cee_linkdns;        /*  CEE link down count                 */ +	u32    fip_linkups;        /*  FIP link up count                   */ +	u32    fip_linkdns;        /*  FIP link up count                   */ +	u32    fip_fails;          /*  FIP fail count                      */ +	u32    mac_invalids;       /*  Invalid mac assigned                */  };  /*   * IOC firmware FCoE port stats   */  struct bfa_fw_fcoe_port_stats_s { -    struct bfa_fw_fcoe_stats_s  fcoe_stats; -    struct bfa_fw_fip_stats_s   fip_stats; +	struct bfa_fw_fcoe_stats_s		fcoe_stats; +	struct bfa_fw_fip_stats_s		fip_stats; +}; + +/** + * @brief LPSM statistics + */ +struct bfa_fw_lpsm_stats_s { +	u32	cls_rx;		/* LPSM cls_rx			*/ +	u32	cls_tx;		/* LPSM cls_tx			*/ +	u32	arbf0_rx;	/* LPSM abrf0 rcvd		*/ +	u32	arbf0_tx;	/* LPSM abrf0 xmit		*/ +	u32	init_rx;	/* LPSM loop init start		*/ +	u32	unexp_hwst;	/* LPSM unknown hw state	*/ +	u32	unexp_frame;	/* LPSM unknown_frame		*/ +	u32	unexp_prim;	/* LPSM unexpected primitive	*/ +	u32	prev_alpa_unavail; /* LPSM prev alpa unavailable */ +	u32	alpa_unavail;	/* LPSM alpa not available	*/ +	u32	lip_rx;		/* LPSM lip rcvd		*/ +	u32	lip_f7f7_rx;	/* LPSM lip f7f7 rcvd		*/ +	u32	lip_f8_rx;	/* LPSM lip f8 rcvd		*/ +	u32	lip_f8f7_rx;	/* LPSM lip f8f7 rcvd		*/ +	u32	lip_other_rx;	/* LPSM lip other rcvd		*/ +	u32	lip_tx;		/* LPSM lip xmit		*/ +	u32	retry_tov;	/* LPSM retry TOV		*/ +	u32	lip_tov;	/* LPSM LIP wait TOV		*/ +	u32	idle_tov;	/* LPSM idle wait TOV		*/ +	u32	arbf0_tov;	/* LPSM arbfo wait TOV		*/ +	u32	stop_loop_tov;	/* LPSM stop loop wait TOV	*/ +	u32	lixa_tov;	/* LPSM lisa wait TOV		*/ +	u32	lixx_tov;	/* LPSM lilp/lirp wait TOV	*/ +	u32	cls_tov;	/* LPSM cls wait TOV		*/ +	u32	sler;		/* LPSM SLER recvd		*/ +	u32	failed;		/* LPSM failed			*/ +	u32	success;	/* LPSM online			*/  };  /* @@ -276,14 +368,15 @@ struct bfa_fw_fcoe_port_stats_s {  struct bfa_fw_fc_uport_stats_s {  	struct bfa_fw_port_snsm_stats_s		snsm_stats;  	struct bfa_fw_port_lksm_stats_s		lksm_stats; +	struct bfa_fw_lpsm_stats_s		lpsm_stats;  };  /*   * IOC firmware FC port stats   */  union bfa_fw_fc_port_stats_s { -	struct bfa_fw_fc_uport_stats_s	fc_stats; -	struct bfa_fw_fcoe_port_stats_s	fcoe_stats; +	struct bfa_fw_fc_uport_stats_s		fc_stats; +	struct bfa_fw_fcoe_port_stats_s		fcoe_stats;  };  /* @@ -303,35 +396,36 @@ struct bfa_fw_fcxchg_stats_s {  	u32	ua_state_inv;  }; -struct bfa_fw_lpsm_stats_s { -	u32	cls_rx; -	u32	cls_tx; -}; -  /*   *  Trunk statistics   */  struct bfa_fw_trunk_stats_s {  	u32 emt_recvd;		/*  Trunk EMT received		*/ -	u32 emt_accepted;		/*  Trunk EMT Accepted		*/ -	u32 emt_rejected;		/*  Trunk EMT rejected		*/ +	u32 emt_accepted;	/*  Trunk EMT Accepted		*/ +	u32 emt_rejected;	/*  Trunk EMT rejected		*/  	u32 etp_recvd;		/*  Trunk ETP received		*/ -	u32 etp_accepted;		/*  Trunk ETP Accepted		*/ -	u32 etp_rejected;		/*  Trunk ETP rejected		*/ +	u32 etp_accepted;	/*  Trunk ETP Accepted		*/ +	u32 etp_rejected;	/*  Trunk ETP rejected		*/  	u32 lr_recvd;		/*  Trunk LR received		*/ -	u32 rsvd;			/*  padding for 64 bit alignment */ +	u32 rsvd;		/*  padding for 64 bit alignment */  }; -struct bfa_fw_advsm_stats_s { +struct bfa_fw_aport_stats_s {  	u32 flogi_sent;		/*  Flogi sent			*/  	u32 flogi_acc_recvd;	/*  Flogi Acc received		*/  	u32 flogi_rjt_recvd;	/*  Flogi rejects received	*/ -	u32 flogi_retries;		/*  Flogi retries		*/ +	u32 flogi_retries;	/*  Flogi retries		*/  	u32 elp_recvd;		/*  ELP received		*/ -	u32 elp_accepted;		/*  ELP Accepted		*/ -	u32 elp_rejected;		/*  ELP rejected		*/ -	u32 elp_dropped;		/*  ELP dropped		*/ +	u32 elp_accepted;	/*  ELP Accepted		*/ +	u32 elp_rejected;	/*  ELP rejected		*/ +	u32 elp_dropped;	/*  ELP dropped			*/ + +	u32 bbcr_lr_count;	/*!< BBCR Link Resets		*/ +	u32 frame_lost_intrs;	/*!< BBCR Frame loss intrs	*/ +	u32 rrdy_lost_intrs;	/*!< BBCR Rrdy loss intrs	*/ + +	u32 rsvd;  };  /* @@ -392,6 +486,14 @@ struct bfa_fw_ct_mod_stats_s {  };  /* + * RDS mod stats + */ +struct bfa_fw_rds_stats_s { +	u32	no_fid_drop_err; /* RDS no fid drop error */ +	u32	rsvd;		 /* 64bit align */ +}; + +/*   * IOC firmware stats   */  struct bfa_fw_stats_s { @@ -400,13 +502,13 @@ struct bfa_fw_stats_s {  	struct bfa_fw_io_stats_s	io_stats;  	struct bfa_fw_port_stats_s	port_stats;  	struct bfa_fw_fcxchg_stats_s	fcxchg_stats; -	struct bfa_fw_lpsm_stats_s	lpsm_stats;  	struct bfa_fw_lps_stats_s	lps_stats;  	struct bfa_fw_trunk_stats_s	trunk_stats; -	struct bfa_fw_advsm_stats_s	advsm_stats; +	struct bfa_fw_aport_stats_s	aport_stats;  	struct bfa_fw_mac_mod_stats_s	macmod_stats;  	struct bfa_fw_ct_mod_stats_s	ctmod_stats;  	struct bfa_fw_eth_sndrcv_stats_s	ethsndrcv_stats; +	struct bfa_fw_rds_stats_s	rds_stats;  };  #define BFA_IOCFC_PATHTOV_MAX	60 @@ -416,6 +518,7 @@ struct bfa_fw_stats_s {   * QoS states   */  enum bfa_qos_state { +	BFA_QOS_DISABLED = 0,		/* QoS is disabled */  	BFA_QOS_ONLINE = 1,		/*  QoS is online */  	BFA_QOS_OFFLINE = 2,		/*  QoS is offline */  }; @@ -439,13 +542,44 @@ enum bfa_qos_bw_alloc {  	BFA_QOS_BW_LOW  =  10,	/*  bandwidth allocation for Low */  };  #pragma pack(1) + +struct bfa_qos_bw_s { +	u8	qos_bw_set; +	u8	high; +	u8	med; +	u8	low; +}; +  /*   * QoS attribute returned in QoS Query   */  struct bfa_qos_attr_s { -	u8		state;		/*  QoS current state */ -	u8		rsvd[3]; -	u32  total_bb_cr;		/*  Total BB Credits */ +	u8	state;		/*  QoS current state */ +	u8	rsvd1[3]; +	u32	total_bb_cr;	/*  Total BB Credits */ +	struct bfa_qos_bw_s qos_bw;	/* QOS bw cfg */ +	struct bfa_qos_bw_s qos_bw_op;	/* QOS bw operational */ +}; + +enum bfa_bbcr_state { +	BFA_BBCR_DISABLED,	/*!< BBCR is disable */ +	BFA_BBCR_ONLINE,	/*!< BBCR is online  */ +	BFA_BBCR_OFFLINE,	/*!< BBCR is offline */ +}; + +enum bfa_bbcr_err_reason { +	BFA_BBCR_ERR_REASON_NONE, /*!< Unknown */ +	BFA_BBCR_ERR_REASON_SPEED_UNSUP, /*!< Port speed < max sup_speed */ +	BFA_BBCR_ERR_REASON_PEER_UNSUP,	/*!< BBCR is disable on peer port */ +	BFA_BBCR_ERR_REASON_NON_BRCD_SW, /*!< Connected to non BRCD switch */ +	BFA_BBCR_ERR_REASON_FLOGI_RJT, /*!< Login rejected by the switch */ +}; + +struct bfa_bbcr_attr_s { +	u8	state; +	u8	peer_bb_scn; +	u8	reason; +	u8	rsvd;  };  /* @@ -467,7 +601,7 @@ struct bfa_qos_vc_attr_s {  	u16  total_vc_count;                    /*  Total VC Count */  	u16  shared_credit;  	u32  elp_opmode_flags; -	struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC];  /*   as many as +	struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC];  /* as many as  							    * total_vc_count */  }; @@ -477,16 +611,16 @@ struct bfa_qos_vc_attr_s {  struct bfa_qos_stats_s {  	u32	flogi_sent;		/*  QoS Flogi sent */  	u32	flogi_acc_recvd;	/*  QoS Flogi Acc received */ -	u32	flogi_rjt_recvd; /*  QoS Flogi rejects received */ +	u32	flogi_rjt_recvd;	/*  QoS Flogi rejects received */  	u32	flogi_retries;		/*  QoS Flogi retries */  	u32	elp_recvd;		/*  QoS ELP received */  	u32	elp_accepted;		/*  QoS ELP Accepted */ -	u32	elp_rejected;       /*  QoS ELP rejected */ -	u32	elp_dropped;        /*  QoS ELP dropped  */ +	u32	elp_rejected;		/*  QoS ELP rejected */ +	u32	elp_dropped;		/*  QoS ELP dropped  */ -	u32	qos_rscn_recvd;     /*  QoS RSCN received */ -	u32	rsvd;		    /* padding for 64 bit alignment */ +	u32	qos_rscn_recvd;		/*  QoS RSCN received */ +	u32	rsvd;			/* padding for 64 bit alignment */  };  /* @@ -494,9 +628,9 @@ struct bfa_qos_stats_s {   */  struct bfa_fcoe_stats_s {  	u64	secs_reset;	/*  Seconds since stats reset	     */ -	u64	cee_linkups;	/*  CEE link up		     */ +	u64	cee_linkups;	/*  CEE link up			     */  	u64	cee_linkdns;	/*  CEE link down		     */ -	u64	fip_linkups;	/*  FIP link up		     */ +	u64	fip_linkups;	/*  FIP link up			     */  	u64	fip_linkdns;	/*  FIP link down		     */  	u64	fip_fails;	/*  FIP failures		     */  	u64	mac_invalids;	/*  Invalid mac assignments	     */ @@ -506,38 +640,38 @@ struct bfa_fcoe_stats_s {  	u64	vlan_timeouts;	/*  Vlan request timeouts	     */  	u64	vlan_invalids;	/*  Vlan invalids		     */  	u64	disc_req;	/*  Discovery requests		     */ -	u64	disc_rsp;	/*  Discovery responses	     */ +	u64	disc_rsp;	/*  Discovery responses		     */  	u64	disc_err;	/*  Discovery error frames	     */  	u64	disc_unsol;	/*  Discovery unsolicited	     */  	u64	disc_timeouts;	/*  Discovery timeouts		     */  	u64	disc_fcf_unavail; /*  Discovery FCF not avail	     */ -	u64	linksvc_unsupp;	/*  FIP link service req unsupp.    */ -	u64	linksvc_err;	/*  FIP link service req errors     */ +	u64	linksvc_unsupp;	/*  FIP link service req unsupp	     */ +	u64	linksvc_err;	/*  FIP link service req errors	     */  	u64	logo_req;	/*  FIP logos received		     */ -	u64	clrvlink_req;	/*  Clear virtual link requests     */ +	u64	clrvlink_req;	/*  Clear virtual link requests	     */  	u64	op_unsupp;	/*  FIP operation unsupp.	     */ -	u64	untagged;	/*  FIP untagged frames	     */ +	u64	untagged;	/*  FIP untagged frames		     */  	u64	txf_ucast;	/*  Tx FCoE unicast frames	     */ -	u64	txf_ucast_vlan;	/*  Tx FCoE unicast vlan frames     */ +	u64	txf_ucast_vlan;	/*  Tx FCoE unicast vlan frames      */  	u64	txf_ucast_octets; /*  Tx FCoE unicast octets	     */  	u64	txf_mcast;	/*  Tx FCoE multicast frames	     */ -	u64	txf_mcast_vlan;	/*  Tx FCoE multicast vlan frames   */ +	u64	txf_mcast_vlan;	/*  Tx FCoE multicast vlan frames    */  	u64	txf_mcast_octets; /*  Tx FCoE multicast octets	     */  	u64	txf_bcast;	/*  Tx FCoE broadcast frames	     */ -	u64	txf_bcast_vlan;	/*  Tx FCoE broadcast vlan frames   */ +	u64	txf_bcast_vlan;	/*  Tx FCoE broadcast vlan frames    */  	u64	txf_bcast_octets; /*  Tx FCoE broadcast octets	     */ -	u64	txf_timeout;	/*  Tx timeouts		     */ +	u64	txf_timeout;	  /*  Tx timeouts		     */  	u64	txf_parity_errors; /*  Transmit parity err	     */ -	u64	txf_fid_parity_errors; /*  Transmit FID parity err  */ +	u64	txf_fid_parity_errors; /*  Transmit FID parity err   */  	u64	rxf_ucast_octets; /*  Rx FCoE unicast octets	     */  	u64	rxf_ucast;	/*  Rx FCoE unicast frames	     */ -	u64	rxf_ucast_vlan;	/*  Rx FCoE unicast vlan frames     */ +	u64	rxf_ucast_vlan;	/*  Rx FCoE unicast vlan frames	     */  	u64	rxf_mcast_octets; /*  Rx FCoE multicast octets	     */  	u64	rxf_mcast;	/*  Rx FCoE multicast frames	     */ -	u64	rxf_mcast_vlan;	/*  Rx FCoE multicast vlan frames   */ +	u64	rxf_mcast_vlan;	/*  Rx FCoE multicast vlan frames    */  	u64	rxf_bcast_octets; /*  Rx FCoE broadcast octets	     */  	u64	rxf_bcast;	/*  Rx FCoE broadcast frames	     */ -	u64	rxf_bcast_vlan;	/*  Rx FCoE broadcast vlan frames   */ +	u64	rxf_bcast_vlan;	/*  Rx FCoE broadcast vlan frames    */  };  /* @@ -566,8 +700,8 @@ struct bfa_itnim_iostats_s {  	u32	input_reqs;		/*  Data in-bound requests	*/  	u32	output_reqs;		/*  Data out-bound requests	*/  	u32	io_comps;		/*  Total IO Completions	*/ -	u32	wr_throughput;		/*  Write data transfered in bytes */ -	u32	rd_throughput;		/*  Read data transfered in bytes  */ +	u32	wr_throughput;		/*  Write data transferred in bytes */ +	u32	rd_throughput;		/*  Read data transferred in bytes  */  	u32	iocomp_ok;		/*  Slowpath IO completions	*/  	u32	iocomp_underrun;	/*  IO underrun		*/ @@ -618,6 +752,7 @@ struct bfa_itnim_iostats_s {  	u32	tm_iocdowns;		/*  TM cleaned-up due to IOC down   */  	u32	tm_cleanups;		/*  TM cleanup requests	*/  	u32	tm_cleanup_comps;	/*  TM cleanup completions	*/ +	u32	rsvd[6];  };  /* Modify char* port_stt[] in bfal_port.c if a new state was added */ @@ -636,6 +771,9 @@ enum bfa_port_states {  	BFA_PORT_ST_FWMISMATCH		= 12,  	BFA_PORT_ST_PREBOOT_DISABLED	= 13,  	BFA_PORT_ST_TOGGLING_QWAIT	= 14, +	BFA_PORT_ST_FAA_MISCONFIG	= 15, +	BFA_PORT_ST_DPORT		= 16, +	BFA_PORT_ST_DDPORT		= 17,  	BFA_PORT_ST_MAX_STATE,  }; @@ -657,9 +795,11 @@ enum bfa_port_type {   */  enum bfa_port_topology {  	BFA_PORT_TOPOLOGY_NONE = 0,	/*  No valid topology */ -	BFA_PORT_TOPOLOGY_P2P  = 1,	/*  P2P only */ -	BFA_PORT_TOPOLOGY_LOOP = 2,	/*  LOOP topology */ -	BFA_PORT_TOPOLOGY_AUTO = 3,	/*  auto topology selection */ +	BFA_PORT_TOPOLOGY_P2P_OLD_VER = 1, /* P2P def for older ver */ +	BFA_PORT_TOPOLOGY_LOOP = 2,	/* LOOP topology */ +	BFA_PORT_TOPOLOGY_AUTO_OLD_VER = 3, /* auto def for older ver */ +	BFA_PORT_TOPOLOGY_AUTO = 4,	/* auto topology selection */ +	BFA_PORT_TOPOLOGY_P2P = 5,	/* P2P only */  };  /* @@ -703,6 +843,7 @@ enum bfa_port_linkstate_rsn {  	BFA_PORT_LINKSTATE_RSN_LOCAL_FAULT	= 9,  	BFA_PORT_LINKSTATE_RSN_REMOTE_FAULT	= 10,  	BFA_PORT_LINKSTATE_RSN_TIMEOUT		= 11, +	BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG	= 12, @@ -732,8 +873,76 @@ enum bfa_port_linkstate_rsn {  	CEE_ISCSI_PRI_PFC_OFF			= 42,  	CEE_ISCSI_PRI_OVERLAP_FCOE_PRI		= 43  }; + +#define MAX_LUN_MASK_CFG 16 + +/* + * Initially flash content may be fff. On making LUN mask enable and disable + * state chnage.  when report lun command is being processed it goes from + * BFA_LUN_MASK_ACTIVE to BFA_LUN_MASK_FETCH and comes back to + * BFA_LUN_MASK_ACTIVE. + */ +enum bfa_ioim_lun_mask_state_s { +	BFA_IOIM_LUN_MASK_INACTIVE = 0, +	BFA_IOIM_LUN_MASK_ACTIVE = 1, +	BFA_IOIM_LUN_MASK_FETCHED = 2, +}; + +enum bfa_lunmask_state_s { +	BFA_LUNMASK_DISABLED = 0x00, +	BFA_LUNMASK_ENABLED = 0x01, +	BFA_LUNMASK_MINCFG = 0x02, +	BFA_LUNMASK_UNINITIALIZED = 0xff, +}; + +/** + * FEC states + */ +enum bfa_fec_state_s { +	BFA_FEC_ONLINE = 1,		/*!< FEC is online */ +	BFA_FEC_OFFLINE = 2,		/*!< FEC is offline */ +	BFA_FEC_OFFLINE_NOT_16G = 3,	/*!< FEC is offline (speed not 16Gig) */ +}; +  #pragma pack(1)  /* + * LUN mask configuration + */ +struct bfa_lun_mask_s { +	wwn_t		lp_wwn; +	wwn_t		rp_wwn; +	struct scsi_lun	lun; +	u8		ua; +	u8		rsvd[3]; +	u16		rp_tag; +	u8		lp_tag; +	u8		state; +}; + +#define MAX_LUN_MASK_CFG 16 +struct bfa_lunmask_cfg_s { +	u32	status; +	u32	rsvd; +	struct bfa_lun_mask_s	lun_list[MAX_LUN_MASK_CFG]; +}; + +struct bfa_throttle_cfg_s { +	u16	is_valid; +	u16	value; +	u32	rsvd; +}; + +struct bfa_defs_fcpim_throttle_s { +	u16	max_value; +	u16	cur_value; +	u16	cfg_value; +	u16	rsvd; +}; + +#define BFA_BB_SCN_DEF 3 +#define BFA_BB_SCN_MAX 0x0F + +/*   *      Physical port configuration   */  struct bfa_port_cfg_s { @@ -743,13 +952,18 @@ struct bfa_port_cfg_s {  	u8	 qos_enabled;	/*  qos enabled or not		*/  	u8	 cfg_hardalpa;	/*  is hard alpa configured	*/  	u8	 hardalpa;	/*  configured hard alpa	*/ -	u16 maxfrsize;	/*  maximum frame size		*/ +	__be16	 maxfrsize;	/*  maximum frame size		*/  	u8	 rx_bbcredit;	/*  receive buffer credits	*/  	u8	 tx_bbcredit;	/*  transmit buffer credits	*/  	u8	 ratelimit;	/*  ratelimit enabled or not	*/  	u8	 trl_def_speed;	/*  ratelimit default speed	*/ -	u16 path_tov;	/*  device path timeout	*/ -	u16 q_depth;	/*  SCSI Queue depth		*/ +	u8	 bb_cr_enabled; /*!< Config state of BB_SCN	*/ +	u8	 bb_scn;	/*!< BB_SCN value for FLOGI Exchg */ +	u8	 faa_state;	/*  FAA enabled/disabled        */ +	u8	 rsvd1; +	u16	 path_tov;	/*  device path timeout	*/ +	u16	 q_depth;	/*  SCSI Queue depth		*/ +	struct bfa_qos_bw_s qos_bw;	/* QOS bandwidth	*/  };  #pragma pack() @@ -760,20 +974,21 @@ struct bfa_port_attr_s {  	/*  	 * Static fields  	 */ -	wwn_t	   nwwn;		/*  node wwn */ -	wwn_t	   pwwn;		/*  port wwn */ -	wwn_t	   factorynwwn;	/*  factory node wwn */ -	wwn_t	   factorypwwn;	/*  factory port wwn */ -	enum fc_cos	cos_supported;	/*  supported class of services */ -	u32	rsvd; +	wwn_t			nwwn;		/*  node wwn */ +	wwn_t			pwwn;		/*  port wwn */ +	wwn_t			factorynwwn;	/*  factory node wwn */ +	wwn_t			factorypwwn;	/*  factory port wwn */ +	enum fc_cos		cos_supported;	/*  supported class of +						 *  services */ +	u32			rsvd;  	struct fc_symname_s	port_symname;	/*  port symbolic name */ -	enum bfa_port_speed speed_supported; /*  supported speeds */ -	bfa_boolean_t   pbind_enabled; +	enum bfa_port_speed	speed_supported; /* supported speeds */ +	bfa_boolean_t		pbind_enabled;  	/*  	 * Configured values  	 */ -	struct bfa_port_cfg_s pport_cfg;	/*  pport cfg */ +	struct bfa_port_cfg_s	pport_cfg;	/*  pport cfg */  	/*  	 * Dynamic field - info from BFA @@ -782,70 +997,70 @@ struct bfa_port_attr_s {  	enum bfa_port_speed	speed;		/*  current speed */  	enum bfa_port_topology	topology;	/*  current topology */  	bfa_boolean_t		beacon;		/*  current beacon status */ -	bfa_boolean_t		link_e2e_beacon; /*  link beacon is on */ -	bfa_boolean_t		plog_enabled;	/*  portlog is enabled */ +	bfa_boolean_t		link_e2e_beacon; /* link beacon is on */ +	bfa_boolean_t		bbsc_op_status;	/* fc credit recovery oper +						 * state */ +	enum bfa_fec_state_s	fec_state;	/*!< current FEC state */  	/*  	 * Dynamic field - info from FCS  	 */ -	u32		pid;		/*  port ID */ +	u32			pid;		/*  port ID */  	enum bfa_port_type	port_type;	/*  current topology */ -	u32		loopback;	/*  external loopback */ -	u32		authfail;	/*  auth fail state */ -	bfa_boolean_t		io_profile;	/*  get it from fcpim mod */ -	u8			pad[4];		/*  for 64-bit alignement */ +	u32			loopback;	/*  external loopback */ +	u32			authfail;	/*  auth fail state */  	/* FCoE specific  */ -	u16		fcoe_vlan; -	u8			rsvd1[6]; +	u16			fcoe_vlan; +	u8			rsvd1[2];  };  /*   *	      Port FCP mappings.   */  struct bfa_port_fcpmap_s { -	char		osdevname[256]; +	char	osdevname[256];  	u32	bus;  	u32	target;  	u32	oslun;  	u32	fcid; -	wwn_t	   nwwn; -	wwn_t	   pwwn; +	wwn_t	nwwn; +	wwn_t	pwwn;  	u64	fcplun; -	char		luid[256]; +	char	luid[256];  };  /*   *	      Port RNID info.   */  struct bfa_port_rnid_s { -	wwn_t	     wwn; +	wwn_t	  wwn;  	u32	  unittype;  	u32	  portid;  	u32	  attached_nodes_num;  	u16	  ip_version;  	u16	  udp_port; -	u8	   ipaddr[16]; +	u8	  ipaddr[16];  	u16	  rsvd;  	u16	  topologydiscoveryflags;  };  #pragma pack(1)  struct bfa_fcport_fcf_s { -	wwn_t	   name;	   /*  FCF name		 */ -	wwn_t	   fabric_name;    /*  Fabric Name	      */ -	u8		fipenabled;	/*  FIP enabled or not */ -	u8		fipfailed;	/*  FIP failed or not	*/ -	u8		resv[2]; -	u8	 pri;	    /*  FCF priority	     */ -	u8	 version;	/*  FIP version used	 */ -	u8	 available;      /*  Available  for  login    */ -	u8	 fka_disabled;   /*  FKA is disabled	  */ -	u8	 maxsz_verified; /*  FCoE max size verified   */ -	u8	 fc_map[3];      /*  FC map		   */ -	u16	vlan;	   /*  FCoE vlan tag/priority   */ -	u32	fka_adv_per;    /*  FIP  ka advert. period   */ -	mac_t	   mac;	    /*  FCF mac		  */ +	wwn_t	name;		/*  FCF name		   */ +	wwn_t	fabric_name;    /*  Fabric Name		   */ +	u8	fipenabled;	/*  FIP enabled or not	   */ +	u8	fipfailed;	/*  FIP failed or not	   */ +	u8	resv[2]; +	u8	pri;		/*  FCF priority	   */ +	u8	version;	/*  FIP version used	   */ +	u8	available;      /*  Available for login    */ +	u8	fka_disabled;   /*  FKA is disabled	   */ +	u8	maxsz_verified; /*  FCoE max size verified */ +	u8	fc_map[3];      /*  FC map		   */ +	__be16	vlan;		/*  FCoE vlan tag/priority */ +	u32	fka_adv_per;    /*  FIP  ka advert. period */ +	mac_t	mac;		/*  FCF mac		   */  };  /* @@ -867,6 +1082,13 @@ struct bfa_trunk_vc_attr_s {  	u16 vc_credits[8];  }; +struct bfa_fcport_loop_info_s { +	u8	myalpa;		/* alpa claimed */ +	u8	alpabm_val;	/* alpa bitmap valid or not (1 or 0) */ +	u8	resvd[6]; +	struct fc_alpabm_s alpabm;	/* alpa bitmap */ +}; +  /*   *	Link state information   */ @@ -875,15 +1097,22 @@ struct bfa_port_link_s {  	u8	 linkstate_rsn;	/*  bfa_port_linkstate_rsn_t */  	u8	 topology;	/*  P2P/LOOP bfa_port_topology */  	u8	 speed;		/*  Link speed (1/2/4/8 G) */ -	u32	linkstate_opt;  /*  Linkstate optional data (debug) */ +	u32	 linkstate_opt; /*  Linkstate optional data (debug) */  	u8	 trunked;	/*  Trunked or not (1 or 0) */ -	u8	 resvd[3]; +	u8	 fec_state;	/*!< State of FEC */ +	u8	 resvd[6];  	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */  	union { -		struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */ -		struct bfa_trunk_vc_attr_s trunk_vc_attr; -		struct bfa_fcport_fcf_s fcf; /*  FCF information (for FCoE) */ -	} vc_fcf; +		struct bfa_fcport_loop_info_s loop_info; +		struct bfa_bbcr_attr_s bbcr_attr; +		union { +			struct bfa_qos_vc_attr_s qos_vc_attr; +					/*  VC info from ELP */ +			struct bfa_trunk_vc_attr_s trunk_vc_attr; +			struct bfa_fcport_fcf_s fcf; +					/*  FCF information (for FCoE) */ +		} vc_fcf; +	} attr;  };  #pragma pack() @@ -929,7 +1158,7 @@ struct bfa_rport_hal_stats_s {  	u32        sm_fwc_del;	    /*  fw create: delete events   */  	u32        sm_fwc_off;	    /*  fw create: offline events  */  	u32        sm_fwc_hwf;	    /*  fw create: IOC down        */ -	u32        sm_fwc_unexp;	    /*  fw create: exception events*/ +	u32        sm_fwc_unexp;    /*  fw create: exception events*/  	u32        sm_on_off;	    /*  online: offline events     */  	u32        sm_on_del;	    /*  online: delete events      */  	u32        sm_on_hwf;	    /*  online: IOC down events    */ @@ -937,25 +1166,25 @@ struct bfa_rport_hal_stats_s {  	u32        sm_fwd_rsp;	    /*  fw delete: fw responses    */  	u32        sm_fwd_del;	    /*  fw delete: delete events   */  	u32        sm_fwd_hwf;	    /*  fw delete: IOC down events */ -	u32        sm_fwd_unexp;	    /*  fw delete: exception events*/ +	u32        sm_fwd_unexp;    /*  fw delete: exception events*/  	u32        sm_off_del;	    /*  offline: delete events     */  	u32        sm_off_on;	    /*  offline: online events     */  	u32        sm_off_hwf;	    /*  offline: IOC down events   */ -	u32        sm_off_unexp;	    /*  offline: exception events  */ -	u32        sm_del_fwrsp;	    /*  delete: fw responses       */ +	u32        sm_off_unexp;    /*  offline: exception events  */ +	u32        sm_del_fwrsp;    /*  delete: fw responses       */  	u32        sm_del_hwf;	    /*  delete: IOC down events    */ -	u32        sm_del_unexp;	    /*  delete: exception events   */ -	u32        sm_delp_fwrsp;	    /*  delete pend: fw responses  */ +	u32        sm_del_unexp;    /*  delete: exception events   */ +	u32        sm_delp_fwrsp;   /*  delete pend: fw responses  */  	u32        sm_delp_hwf;	    /*  delete pend: IOC downs     */ -	u32        sm_delp_unexp;	    /*  delete pend: exceptions    */ -	u32        sm_offp_fwrsp;	    /*  off-pending: fw responses  */ +	u32        sm_delp_unexp;   /*  delete pend: exceptions    */ +	u32        sm_offp_fwrsp;   /*  off-pending: fw responses  */  	u32        sm_offp_del;	    /*  off-pending: deletes       */  	u32        sm_offp_hwf;	    /*  off-pending: IOC downs     */ -	u32        sm_offp_unexp;	    /*  off-pending: exceptions    */ +	u32        sm_offp_unexp;   /*  off-pending: exceptions    */  	u32        sm_iocd_off;	    /*  IOC down: offline events   */  	u32        sm_iocd_del;	    /*  IOC down: delete events    */  	u32        sm_iocd_on;	    /*  IOC down: online events    */ -	u32        sm_iocd_unexp;	    /*  IOC down: exceptions       */ +	u32        sm_iocd_unexp;   /*  IOC down: exceptions       */  	u32        rsvd;  };  #pragma pack(1) @@ -963,9 +1192,9 @@ struct bfa_rport_hal_stats_s {   *  Rport's QoS attributes   */  struct bfa_rport_qos_attr_s { -	u8			qos_priority;  /*  rport's QoS priority   */ -	u8			rsvd[3]; -	u32	       qos_flow_id;	  /*  QoS flow Id	 */ +	u8		qos_priority;	/*  rport's QoS priority   */ +	u8		rsvd[3]; +	u32		qos_flow_id;	/*  QoS flow Id	 */  };  #pragma pack() @@ -988,6 +1217,19 @@ struct bfa_itnim_ioprofile_s {  };  /* + *	vHBA port attribute values. + */ +struct bfa_vhba_attr_s { +	wwn_t	nwwn;       /* node wwn */ +	wwn_t	pwwn;       /* port wwn */ +	u32	pid;        /* port ID */ +	bfa_boolean_t       io_profile; /* get it from fcpim mod */ +	bfa_boolean_t       plog_enabled;   /* portlog is enabled */ +	u16	path_tov; +	u8	rsvd[2]; +}; + +/*   * FC physical port statistics.   */  struct bfa_port_fc_stats_s { @@ -995,6 +1237,9 @@ struct bfa_port_fc_stats_s {  	u64     tx_frames;      /*  Tx frames                   */  	u64     tx_words;       /*  Tx words                    */  	u64     tx_lip;         /*  Tx LIP                      */ +	u64	tx_lip_f7f7;	/*  Tx LIP_F7F7		*/ +	u64	tx_lip_f8f7;	/*  Tx LIP_F8F7		*/ +	u64	tx_arbf0;	/*  Tx ARB F0			*/  	u64     tx_nos;         /*  Tx NOS                      */  	u64     tx_ols;         /*  Tx OLS                      */  	u64     tx_lr;          /*  Tx LR                       */ @@ -1002,6 +1247,9 @@ struct bfa_port_fc_stats_s {  	u64     rx_frames;      /*  Rx frames                   */  	u64     rx_words;       /*  Rx words                    */  	u64     lip_count;      /*  Rx LIP                      */ +	u64	rx_lip_f7f7;	/*  Rx LIP_F7F7		*/ +	u64	rx_lip_f8f7;	/*  Rx LIP_F8F7		*/ +	u64	rx_arbf0;	/*  Rx ARB F0			*/  	u64     nos_count;      /*  Rx NOS                      */  	u64     ols_count;      /*  Rx OLS                      */  	u64     lr_count;       /*  Rx LR                       */ @@ -1020,6 +1268,12 @@ struct bfa_port_fc_stats_s {  	u64     bad_os_count;   /*  Invalid ordered sets        */  	u64     err_enc_out;    /*  Encoding err nonframe_8b10b */  	u64     err_enc;        /*  Encoding err frame_8b10b    */ +	u64	bbcr_frames_lost; /*!< BBCR Frames Lost */ +	u64	bbcr_rrdys_lost; /*!< BBCR RRDYs Lost */ +	u64	bbcr_link_resets; /*!< BBCR Link Resets */ +	u64	bbcr_frame_lost_intrs; /*!< BBCR Frame loss intrs */ +	u64	bbcr_rrdy_lost_intrs; /*!< BBCR Rrdy loss intrs */ +	u64	loop_timeouts;	/*  Loop timeouts		*/  };  /* @@ -1078,4 +1332,131 @@ union bfa_port_stats_u {  	struct bfa_port_eth_stats_s     eth;  }; +struct bfa_port_cfg_mode_s { +	u16		max_pf; +	u16		max_vf; +	enum bfa_mode_s	mode; +}; + +#pragma pack(1) + +#define BFA_CEE_LLDP_MAX_STRING_LEN	(128) +#define BFA_CEE_DCBX_MAX_PRIORITY	(8) +#define BFA_CEE_DCBX_MAX_PGID		(8) + +struct bfa_cee_lldp_str_s { +	u8	sub_type; +	u8	len; +	u8	rsvd[2]; +	u8	value[BFA_CEE_LLDP_MAX_STRING_LEN]; +}; + +struct bfa_cee_lldp_cfg_s { +	struct bfa_cee_lldp_str_s chassis_id; +	struct bfa_cee_lldp_str_s port_id; +	struct bfa_cee_lldp_str_s port_desc; +	struct bfa_cee_lldp_str_s sys_name; +	struct bfa_cee_lldp_str_s sys_desc; +	struct bfa_cee_lldp_str_s mgmt_addr; +	u16	time_to_live; +	u16	enabled_system_cap; +}; + +/* CEE/DCBX parameters */ +struct bfa_cee_dcbx_cfg_s { +	u8	pgid[BFA_CEE_DCBX_MAX_PRIORITY]; +	u8	pg_percentage[BFA_CEE_DCBX_MAX_PGID]; +	u8	pfc_primap; /* bitmap of priorties with PFC enabled */ +	u8	fcoe_primap; /* bitmap of priorities used for FcoE traffic */ +	u8	iscsi_primap; /* bitmap of priorities used for iSCSI traffic */ +	u8	dcbx_version; /* operating version:CEE or preCEE */ +	u8	lls_fcoe; /* FCoE Logical Link Status */ +	u8	lls_lan; /* LAN Logical Link Status */ +	u8	rsvd[2]; +}; + +/* CEE Query */ +struct bfa_cee_attr_s { +	u8	cee_status; +	u8	error_reason; +	struct bfa_cee_lldp_cfg_s lldp_remote; +	struct bfa_cee_dcbx_cfg_s dcbx_remote; +	mac_t src_mac; +	u8	link_speed; +	u8	nw_priority; +	u8	filler[2]; +}; + +/* LLDP/DCBX/CEE Statistics */ +struct bfa_cee_stats_s { +	u32		lldp_tx_frames;		/* LLDP Tx Frames */ +	u32		lldp_rx_frames;		/* LLDP Rx Frames */ +	u32		lldp_rx_frames_invalid; /* LLDP Rx Frames invalid */ +	u32		lldp_rx_frames_new;     /* LLDP Rx Frames new */ +	u32		lldp_tlvs_unrecognized; /* LLDP Rx unrecog. TLVs */ +	u32		lldp_rx_shutdown_tlvs;  /* LLDP Rx shutdown TLVs */ +	u32		lldp_info_aged_out;     /* LLDP remote info aged */ +	u32		dcbx_phylink_ups;       /* DCBX phy link ups */ +	u32		dcbx_phylink_downs;     /* DCBX phy link downs */ +	u32		dcbx_rx_tlvs;           /* DCBX Rx TLVs */ +	u32		dcbx_rx_tlvs_invalid;   /* DCBX Rx TLVs invalid */ +	u32		dcbx_control_tlv_error; /* DCBX control TLV errors */ +	u32		dcbx_feature_tlv_error; /* DCBX feature TLV errors */ +	u32		dcbx_cee_cfg_new;       /* DCBX new CEE cfg rcvd */ +	u32		cee_status_down;        /* DCB status down */ +	u32		cee_status_up;          /* DCB status up */ +	u32		cee_hw_cfg_changed;     /* DCB hw cfg changed */ +	u32		cee_rx_invalid_cfg;     /* DCB invalid cfg */ +}; + +#pragma pack() + +/* + *			AEN related definitions + */ +#define BFAD_NL_VENDOR_ID (((u64)0x01 << SCSI_NL_VID_TYPE_SHIFT) \ +			   | BFA_PCI_VENDOR_ID_BROCADE) + +/* BFA remote port events */ +enum bfa_rport_aen_event { +	BFA_RPORT_AEN_ONLINE     = 1,   /* RPort online event */ +	BFA_RPORT_AEN_OFFLINE    = 2,   /* RPort offline event */ +	BFA_RPORT_AEN_DISCONNECT = 3,   /* RPort disconnect event */ +	BFA_RPORT_AEN_QOS_PRIO   = 4,   /* QOS priority change event */ +	BFA_RPORT_AEN_QOS_FLOWID = 5,   /* QOS flow Id change event */ +}; + +struct bfa_rport_aen_data_s { +	u16             vf_id;  /* vf_id of this logical port */ +	u16             rsvd[3]; +	wwn_t           ppwwn;  /* WWN of its physical port */ +	wwn_t           lpwwn;  /* WWN of this logical port */ +	wwn_t           rpwwn;  /* WWN of this remote port */ +	union { +		struct bfa_rport_qos_attr_s qos; +	} priv; +}; + +union bfa_aen_data_u { +	struct bfa_adapter_aen_data_s	adapter; +	struct bfa_port_aen_data_s	port; +	struct bfa_lport_aen_data_s	lport; +	struct bfa_rport_aen_data_s	rport; +	struct bfa_itnim_aen_data_s	itnim; +	struct bfa_audit_aen_data_s	audit; +	struct bfa_ioc_aen_data_s	ioc; +}; + +#define BFA_AEN_MAX_ENTRY	512 + +struct bfa_aen_entry_s { +	struct list_head	qe; +	enum bfa_aen_category   aen_category; +	u32                     aen_type; +	union bfa_aen_data_u    aen_data; +	struct timeval          aen_tv; +	u32                     seq_num; +	u32                     bfad_num; +}; +  #endif /* __BFA_DEFS_SVC_H__ */ diff --git a/drivers/scsi/bfa/bfa_drv.c b/drivers/scsi/bfa/bfa_drv.c deleted file mode 100644 index 0222d7c88a9..00000000000 --- a/drivers/scsi/bfa/bfa_drv.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. - * All rights reserved - * www.brocade.com - * - * Linux driver for Brocade Fibre Channel Host Bus Adapter. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License (GPL) Version 2 as - * published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - */ - -#include "bfa_modules.h" - -/* - * BFA module list terminated by NULL - */ -struct bfa_module_s *hal_mods[] = { -	&hal_mod_sgpg, -	&hal_mod_fcport, -	&hal_mod_fcxp, -	&hal_mod_lps, -	&hal_mod_uf, -	&hal_mod_rport, -	&hal_mod_fcpim, -	NULL -}; - -/* - * Message handlers for various modules. - */ -bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = { -	bfa_isr_unhandled,	/* NONE */ -	bfa_isr_unhandled,	/* BFI_MC_IOC */ -	bfa_isr_unhandled,	/* BFI_MC_DIAG */ -	bfa_isr_unhandled,	/* BFI_MC_FLASH */ -	bfa_isr_unhandled,	/* BFI_MC_CEE */ -	bfa_fcport_isr,		/* BFI_MC_FCPORT */ -	bfa_isr_unhandled,	/* BFI_MC_IOCFC */ -	bfa_isr_unhandled,	/* BFI_MC_LL */ -	bfa_uf_isr,		/* BFI_MC_UF */ -	bfa_fcxp_isr,		/* BFI_MC_FCXP */ -	bfa_lps_isr,		/* BFI_MC_LPS */ -	bfa_rport_isr,		/* BFI_MC_RPORT */ -	bfa_itnim_isr,		/* BFI_MC_ITNIM */ -	bfa_isr_unhandled,	/* BFI_MC_IOIM_READ */ -	bfa_isr_unhandled,	/* BFI_MC_IOIM_WRITE */ -	bfa_isr_unhandled,	/* BFI_MC_IOIM_IO */ -	bfa_ioim_isr,		/* BFI_MC_IOIM */ -	bfa_ioim_good_comp_isr,	/* BFI_MC_IOIM_IOCOM */ -	bfa_tskim_isr,		/* BFI_MC_TSKIM */ -	bfa_isr_unhandled,	/* BFI_MC_SBOOT */ -	bfa_isr_unhandled,	/* BFI_MC_IPFC */ -	bfa_isr_unhandled,	/* BFI_MC_PORT */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -	bfa_isr_unhandled,	/* --------- */ -}; - - -/* - * Message handlers for mailbox command classes - */ -bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = { -	NULL, -	NULL,			/* BFI_MC_IOC   */ -	NULL,			/* BFI_MC_DIAG  */ -	NULL,		/* BFI_MC_FLASH */ -	NULL,			/* BFI_MC_CEE   */ -	NULL,			/* BFI_MC_PORT  */ -	bfa_iocfc_isr,		/* BFI_MC_IOCFC */ -	NULL, -}; - - - -void -bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi) -{ -	struct bfa_port_s	*port = &bfa->modules.port; -	u32		dm_len; -	u8			*dm_kva; -	u64		dm_pa; - -	dm_len = bfa_port_meminfo(); -	dm_kva = bfa_meminfo_dma_virt(mi); -	dm_pa  = bfa_meminfo_dma_phys(mi); - -	memset(port, 0, sizeof(struct bfa_port_s)); -	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod); -	bfa_port_mem_claim(port, dm_kva, dm_pa); - -	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len; -	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len; -} diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index e929d25b09e..64069a0a3d0 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -18,10 +18,9 @@  #ifndef __BFA_FC_H__  #define __BFA_FC_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h"  typedef u64 wwn_t; -typedef u64 lun_t;  #define WWN_NULL	(0)  #define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */ @@ -40,7 +39,6 @@ struct mac_s { u8 mac[MAC_ADDRLEN]; };  struct scsi_cdb_s {  	u8         scsi_cdb[SCSI_MAX_CDBLEN];  }; -#define scsi_cdb_t struct scsi_cdb_s  /* ------------------------------------------------------------   * SCSI status byte values @@ -63,7 +61,7 @@ struct scsi_cdb_s {   * Fibre Channel Header Structure (FCHS) definition   */  struct fchs_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u32        routing:4;	/* routing bits */  	u32        cat_info:4;	/* category info */  #else @@ -75,34 +73,19 @@ struct fchs_s {  	u32        cs_ctl:8;	/* class specific control */  	u32        s_id:24;	/* source identifier */ -	u32        type:8;		/* data structure type */ +	u32        type:8;	/* data structure type */  	u32        f_ctl:24;	/* initial frame control */ -	u8         seq_id;		/* sequence identifier */ -	u8         df_ctl;		/* data field control */ +	u8         seq_id;	/* sequence identifier */ +	u8         df_ctl;	/* data field control */  	u16        seq_cnt;	/* sequence count */ -	u16        ox_id;		/* originator exchange ID */ -	u16        rx_id;		/* responder exchange ID */ +	__be16     ox_id;	/* originator exchange ID */ +	u16        rx_id;	/* responder exchange ID */  	u32        ro;		/* relative offset */  }; -#define FC_SOF_LEN		4 -#define FC_EOF_LEN		4 -#define FC_CRC_LEN		4 - -/* - * Fibre Channel BB_E Header Structure - */ -struct fcbbehs_s { -	u16	ver_rsvd; -	u32	rsvd[2]; -	u32	rsvd__sof; -}; - -#define FC_SEQ_ID_MAX		256 -  /*   * routing bit definitions   */ @@ -149,22 +132,6 @@ enum {  };  /* - * information category for Link Control - */ -enum { -	FC_CAT_ACK_1		= 0x00, -	FC_CAT_ACK_0_N		= 0x01, -	FC_CAT_P_RJT		= 0x02, -	FC_CAT_F_RJT		= 0x03, -	FC_CAT_P_BSY		= 0x04, -	FC_CAT_F_BSY_DATA	= 0x05, -	FC_CAT_F_BSY_LINK_CTL	= 0x06, -	FC_CAT_F_LCR		= 0x07, -	FC_CAT_NTY		= 0x08, -	FC_CAT_END		= 0x09, -}; - -/*   * Type Field Definitions. FC-PH Section 18.5 pg. 165   */  enum { @@ -182,10 +149,6 @@ enum {  	FC_TYPE_MAX		= 256,	/* 256 FC-4 types */  }; -struct fc_fc4types_s { -	u8         bits[FC_TYPE_MAX / 8]; -}; -  /*   * Frame Control Definitions. FC-PH Table-45. pg. 168   */ @@ -288,7 +251,6 @@ enum {  	FC_ELS_AUTH = 0x90,	/* Authentication. Ref FC-SP */  	FC_ELS_RFCN = 0x97,	/* Request Fabric Change Notification. Ref  				 *FC-SP */ -  };  /* @@ -314,12 +276,12 @@ enum {   * FC-PH-x. Figure-76. pg. 308.   */  struct fc_plogi_csp_s { -	u8         verhi;	/* FC-PH high version */ -	u8         verlo;	/* FC-PH low version */ -	u16        bbcred;	/* BB_Credit */ +	u8		verhi;		/* FC-PH high version */ +	u8		verlo;		/* FC-PH low version */ +	__be16		bbcred;		/* BB_Credit */ -#ifdef __BIGENDIAN -	u8         ciro:1,		/* continuously increasing RO */ +#ifdef __BIG_ENDIAN +	u8		ciro:1,		/* continuously increasing RO */  			rro:1,		/* random relative offset */  			npiv_supp:1,	/* NPIV supported */  			port_type:1,	/* N_Port/F_port */ @@ -328,7 +290,7 @@ struct fc_plogi_csp_s {  			vvl_info:1,	/* VVL Info included */  			reserved1:1; -	u8         hg_supp:1, +	u8		hg_supp:1,  			query_dbc:1,  			security:1,  			sync_cap:1, @@ -337,7 +299,7 @@ struct fc_plogi_csp_s {  			cisc:1,		/* continuously increasing seq count */  			payload:1;  #else -	u8         reserved2:2, +	u8		reserved2:2,  			resolution:1,	/* ms/ns ED_TOV resolution */  			altbbcred:1,	/* alternate BB_Credit */  			port_type:1,	/* N_Port/F_port */ @@ -345,7 +307,7 @@ struct fc_plogi_csp_s {  			rro:1,		/* random relative offset */  			ciro:1;		/* continuously increasing RO */ -	u8         payload:1, +	u8		payload:1,  			cisc:1,		/* continuously increasing seq count */  			dh_dup_supp:1,  			r_t_tov:1, @@ -354,13 +316,10 @@ struct fc_plogi_csp_s {  			query_dbc:1,  			hg_supp:1;  #endif - -	u16        rxsz;		/* recieve data_field size */ - -	u16        conseq; -	u16        ro_bitmap; - -	u32        e_d_tov; +	__be16		rxsz;		/* receive data_field size */ +	__be16		conseq; +	__be16		ro_bitmap; +	__be32		e_d_tov;  };  /* @@ -368,12 +327,11 @@ struct fc_plogi_csp_s {   * FC-PH-x. Figure 78. pg. 318.   */  struct fc_plogi_clp_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u32        class_valid:1;  	u32        intermix:1;	/* class intermix supported if set =1. -					 * valid only for class1. Reserved for -					 * class2 & class3 -					 */ +				 * valid only for class1. Reserved for +				 * class2 & class3 */  	u32        reserved1:2;  	u32        sequential:1;  	u32        reserved2:3; @@ -382,12 +340,10 @@ struct fc_plogi_clp_s {  	u32        sequential:1;  	u32        reserved1:2;  	u32        intermix:1;	/* class intermix supported if set =1. -					 * valid only for class1. Reserved for -					 * class2 & class3 -					 */ +				 * valid only for class1. Reserved for +				 * class2 & class3 */  	u32        class_valid:1;  #endif -  	u32        reserved3:24;  	u32        reserved4:16; @@ -395,7 +351,7 @@ struct fc_plogi_clp_s {  	u32        reserved5:8;  	u32        conseq:8; -	u32        e2e_credit:16;	/* end to end credit */ +	u32        e2e_credit:16; /* end to end credit */  	u32        reserved7:8;  	u32        ospx:8; @@ -409,24 +365,24 @@ struct fc_plogi_clp_s {   * PLOGI els command and reply payload   */  struct fc_logi_s { -	struct fc_els_cmd_s els_cmd;	/* ELS command code */ -	struct fc_plogi_csp_s csp;		/* common service params */ -	wwn_t           port_name; -	wwn_t           node_name; -	struct fc_plogi_clp_s class1;		/* class 1 service parameters */ -	struct fc_plogi_clp_s class2;		/* class 2 service parameters */ -	struct fc_plogi_clp_s class3;		/* class 3 service parameters */ -	struct fc_plogi_clp_s class4;		/* class 4 service parameters */ -	u8         vvl[16];	/* vendor version level */ +	struct fc_els_cmd_s	els_cmd;	/* ELS command code */ +	struct fc_plogi_csp_s	csp;		/* common service params */ +	wwn_t			port_name; +	wwn_t			node_name; +	struct fc_plogi_clp_s	class1;		/* class 1 service parameters */ +	struct fc_plogi_clp_s	class2;		/* class 2 service parameters */ +	struct fc_plogi_clp_s	class3;		/* class 3 service parameters */ +	struct fc_plogi_clp_s	class4;		/* class 4 service parameters */ +	u8			vvl[16];	/* vendor version level */  };  /*   * LOGO els command payload   */  struct fc_logo_s { -	struct fc_els_cmd_s els_cmd;	/* ELS command code */ -	u32        res1:8; -	u32        nport_id:24;	/* N_Port identifier of source */ +	struct fc_els_cmd_s	els_cmd;	/* ELS command code */ +	u32			res1:8; +	u32		nport_id:24;	/* N_Port identifier of source */  	wwn_t           orig_port_name;	/* Port name of the LOGO originator */  }; @@ -435,12 +391,12 @@ struct fc_logo_s {   */  struct fc_adisc_s {  	struct fc_els_cmd_s els_cmd;	/* ELS command code */ -	u32        res1:8; -	u32        orig_HA:24;	/* originator hard address */ -	wwn_t           orig_port_name;	/* originator port name */ -	wwn_t           orig_node_name;	/* originator node name */ -	u32        res2:8; -	u32        nport_id:24;	/* originator NPortID */ +	u32		res1:8; +	u32		orig_HA:24;	/* originator hard address */ +	wwn_t		orig_port_name;	/* originator port name */ +	wwn_t		orig_node_name;	/* originator node name */ +	u32		res2:8; +	u32		nport_id:24;	/* originator NPortID */  };  /* @@ -466,7 +422,7 @@ struct fc_exch_status_blk_s {  struct fc_res_s {  	struct fc_els_cmd_s els_cmd;	/* ELS command code */  	u32        res1:8; -	u32        nport_id:24;	/* N_Port identifier of source */ +	u32        nport_id:24;		/* N_Port identifier of source */  	u32        oxid:16;  	u32        rxid:16;  	u8         assoc_hdr[32]; @@ -512,8 +468,8 @@ struct fc_rec_acc_s {  	u32        orig_id:24;	/* N_Port id of exchange originator */  	u32        res2:8;  	u32        resp_id:24;	/* N_Port id of exchange responder */ -	u32        count;		/* data transfer count */ -	u32        e_stat;		/* exchange status */ +	u32        count;	/* data transfer count */ +	u32        e_stat;	/* exchange status */  };  /* @@ -533,7 +489,7 @@ struct fc_rsi_s {   */  struct fc_prli_params_s {  	u32        reserved:16; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u32        reserved1:5;  	u32        rec_support:1;  	u32        task_retry_id:1; @@ -575,7 +531,7 @@ enum {  struct fc_prli_params_page_s {  	u32        type:8;  	u32        codext:8; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u32        origprocasv:1;  	u32        rsppav:1;  	u32        imagepair:1; @@ -611,18 +567,14 @@ struct fc_prli_s {  struct fc_prlo_params_page_s {  	u32        type:8;  	u32        type_ext:8; -#ifdef __BIGENDIAN -	u32        opa_valid:1;	/* originator process associator -					 * valid -					 */ +#ifdef __BIG_ENDIAN +	u32        opa_valid:1;	/* originator process associator valid */  	u32        rpa_valid:1;	/* responder process associator valid */  	u32        res1:14;  #else  	u32        res1:14;  	u32        rpa_valid:1;	/* responder process associator valid */ -	u32        opa_valid:1;	/* originator process associator -					 * valid -					 */ +	u32        opa_valid:1;	/* originator process associator valid */  #endif  	u32        orig_process_assc;  	u32        resp_process_assc; @@ -647,18 +599,14 @@ struct fc_prlo_acc_params_page_s {  	u32        type:8;  	u32        type_ext:8; -#ifdef __BIGENDIAN -	u32        opa_valid:1;	/* originator process associator -					 * valid -					 */ +#ifdef __BIG_ENDIAN +	u32        opa_valid:1;	/* originator process associator valid */  	u32        rpa_valid:1;	/* responder process associator valid */  	u32        res1:14;  #else  	u32        res1:14;  	u32        rpa_valid:1;	/* responder process associator valid */ -	u32        opa_valid:1;	/* originator process associator -					 * valid -					 */ +	u32        opa_valid:1;	/* originator process associator valid */  #endif  	u32        orig_process_assc;  	u32        resp_process_assc; @@ -715,9 +663,9 @@ enum {   * LS_RJT els reply payload   */  struct fc_ls_rjt_s { -	struct fc_els_cmd_s els_cmd;		/* ELS command code */ +	struct fc_els_cmd_s els_cmd;	/* ELS command code */  	u32        res1:8; -	u32        reason_code:8;		/* Reason code for reject */ +	u32        reason_code:8;	/* Reason code for reject */  	u32        reason_code_expl:8;	/* Reason code explanation */  	u32        vendor_unique:8;	/* Vendor specific */  }; @@ -779,12 +727,12 @@ struct fc_rrq_s {   */  struct fc_ba_acc_s {  	u32        seq_id_valid:8;	/* set to 0x00 for Abort Exchange */ -	u32        seq_id:8;	/* invalid for Abort Exchange */ +	u32        seq_id:8;		/* invalid for Abort Exchange */  	u32        res2:16; -	u32        ox_id:16;	/* OX_ID from ABTS frame */ -	u32        rx_id:16;	/* RX_ID from ABTS frame */ +	u32        ox_id:16;		/* OX_ID from ABTS frame */ +	u32        rx_id:16;		/* RX_ID from ABTS frame */  	u32        low_seq_cnt:16;	/* set to 0x0000 for Abort Exchange */ -	u32        high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */ +	u32        high_seq_cnt:16;	/* set to 0xFFFF for Abort Exchange */  };  /* @@ -794,17 +742,17 @@ struct fc_ba_rjt_s {  	u32        res1:8;		/* Reserved */  	u32        reason_code:8;	/* reason code for reject */  	u32        reason_expl:8;	/* reason code explanation */ -	u32        vendor_unique:8;/* vendor unique reason code,set to 0 */ +	u32        vendor_unique:8; /* vendor unique reason code,set to 0 */  };  /*   * TPRLO logout parameter page   */  struct fc_tprlo_params_page_s { -u32        type:8; -u32        type_ext:8; +	u32        type:8; +	u32        type_ext:8; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u32        opa_valid:1;  	u32        rpa_valid:1;  	u32        tpo_nport_valid:1; @@ -864,16 +812,16 @@ enum fc_rscn_format {  };  struct fc_rscn_event_s { -	u32        format:2; -	u32        qualifier:4; -	u32        resvd:2; -	u32        portid:24; +	u32	format:2; +	u32	qualifier:4; +	u32	resvd:2; +	u32	portid:24;  };  struct fc_rscn_pl_s { -	u8         command; -	u8         pagelen; -	u16        payldlen; +	u8	command; +	u8	pagelen; +	__be16	payldlen;  	struct fc_rscn_event_s event[1];  }; @@ -887,7 +835,6 @@ struct fc_echo_s {  /*   * RNID els command   */ -  #define RNID_NODEID_DATA_FORMAT_COMMON			0x00  #define RNID_NODEID_DATA_FORMAT_FCP3			0x08  #define RNID_NODEID_DATA_FORMAT_DISCOVERY		0xDF @@ -920,15 +867,15 @@ struct fc_rnid_cmd_s {   */  struct fc_rnid_common_id_data_s { -	wwn_t           port_name; +	wwn_t		port_name;  	wwn_t           node_name;  };  struct fc_rnid_general_topology_data_s {  	u32        vendor_unique[4]; -	u32        asso_type; +	__be32     asso_type;  	u32        phy_port_num; -	u32        num_attached_nodes; +	__be32     num_attached_nodes;  	u32        node_mgmt:8;  	u32        ip_version:8;  	u32        udp_tcp_port_num:16; @@ -980,59 +927,17 @@ enum fc_rpsc_op_speed {  	RPSC_OP_SPEED_8G = 0x0800,  	RPSC_OP_SPEED_16G = 0x0400, -	RPSC_OP_SPEED_NOT_EST = 0x0001,	/*! speed not established */ +	RPSC_OP_SPEED_NOT_EST = 0x0001,	/* speed not established */  };  struct fc_rpsc_speed_info_s { -	u16        port_speed_cap;	/*! see enum fc_rpsc_speed_cap */ -	u16        port_op_speed;	/*! see enum fc_rpsc_op_speed */ -}; - -enum link_e2e_beacon_subcmd { -	LINK_E2E_BEACON_ON = 1, -	LINK_E2E_BEACON_OFF = 2 -}; - -enum beacon_type { -	BEACON_TYPE_NORMAL	= 1,	/*! Normal Beaconing. Green */ -	BEACON_TYPE_WARN	= 2,	/*! Warning Beaconing. Yellow/Amber */ -	BEACON_TYPE_CRITICAL	= 3	/*! Critical Beaconing. Red */ -}; - -struct link_e2e_beacon_param_s { -	u8         beacon_type;	/* Beacon Type. See enum beacon_type */ -	u8         beacon_frequency; -					/* Beacon frequency. Number of blinks -					 * per 10 seconds -					 */ -	u16        beacon_duration;/* Beacon duration (in Seconds). The -					 * command operation should be -					 * terminated at the end of this -					 * timeout value. -					 * -					 * Ignored if diag_sub_cmd is -					 * LINK_E2E_BEACON_OFF. -					 * -					 * If 0, beaconing will continue till a -					 * BEACON OFF request is received -					 */ -}; - -/* - * Link E2E beacon request/good response format. - * For LS_RJTs use struct fc_ls_rjt_s - */ -struct link_e2e_beacon_req_s { -	u32        ls_code;	/*! FC_ELS_E2E_LBEACON in requests * -					 *or FC_ELS_ACC in good replies */ -	u32        ls_sub_cmd;	/*! See enum link_e2e_beacon_subcmd */ -	struct link_e2e_beacon_param_s beacon_parm; +	__be16        port_speed_cap;	/* see enum fc_rpsc_speed_cap */ +	__be16        port_op_speed;	/* see enum fc_rpsc_op_speed */  };  /*   * If RPSC request is sent to the Domain Controller, the request is for - * all the ports within that domain (TODO - I don't think FOS implements - * this...). + * all the ports within that domain.   */  struct fc_rpsc_cmd_s {  	struct fc_els_cmd_s els_cmd; @@ -1056,9 +961,9 @@ struct fc_rpsc_acc_s {  struct fc_rpsc2_cmd_s {  	struct fc_els_cmd_s els_cmd; -	u32	token; +	__be32	token;  	u16	resvd; -	u16	num_pids;	/* Number of pids in the request */ +	__be16	num_pids;		/* Number of pids in the request */  	struct  {  		u32	rsvd1:8;  		u32	pid:24;		/* port identifier */ @@ -1072,16 +977,17 @@ enum fc_rpsc2_port_type {  	RPSC2_PORT_TYPE_NPIV_PORT  = 0x5f,  	RPSC2_PORT_TYPE_NPORT_TRUNK  = 0x6f,  }; +  /*   * RPSC2 portInfo entry structure   */  struct fc_rpsc2_port_info_s { -    u32    pid;        /* PID */ -    u16    resvd1; -    u16    index;      /* port number / index */ -    u8     resvd2; -    u8	   type;	/* port type N/NL/... */ -    u16    speed;      /* port Operating Speed */ +	__be32	pid;		/* PID */ +	u16	resvd1; +	__be16	index;		/* port number / index */ +	u8	resvd2; +	u8	type;		/* port type N/NL/... */ +	__be16	speed;		/* port Operating Speed */  };  /* @@ -1090,8 +996,8 @@ struct fc_rpsc2_port_info_s {  struct fc_rpsc2_acc_s {  	u8        els_cmd;  	u8        resvd; -    u16       num_pids;  /* Number of pids in the request */ -    struct fc_rpsc2_port_info_s port_info[1];    /* port information */ +	__be16    num_pids; /* Number of pids in the request */ +	struct fc_rpsc2_port_info_s port_info[1]; /* port information */  };  /* @@ -1111,17 +1017,17 @@ struct fc_symname_s {  };  struct fc_alpabm_s { -	u8         alpa_bm[FC_ALPA_MAX / 8]; +	u8	alpa_bm[FC_ALPA_MAX / 8];  };  /*   * protocol default timeout values   */ -#define FC_ED_TOV		2 -#define FC_REC_TOV		(FC_ED_TOV + 1) -#define FC_RA_TOV		10 -#define FC_ELS_TOV		(2 * FC_RA_TOV) -#define FC_FCCT_TOV		(3 * FC_RA_TOV) +#define FC_ED_TOV	2 +#define FC_REC_TOV	(FC_ED_TOV + 1) +#define FC_RA_TOV	10 +#define FC_ELS_TOV	(2 * FC_RA_TOV) +#define FC_FCCT_TOV	(3 * FC_RA_TOV)  /*   * virtual fabric related defines @@ -1148,59 +1054,34 @@ struct fc_vft_s {  };  /* - * FCP - */ -enum { -	FCP_RJT		= 0x01000000,	/* SRR reject */ -	FCP_SRR_ACCEPT	= 0x02000000,	/* SRR accept */ -	FCP_SRR		= 0x14000000,	/* Sequence Retransmission Request */ -}; - -/* - * SRR FC-4 LS payload - */ -struct fc_srr_s { -	u32	ls_cmd; -	u32        ox_id:16;	/* ox-id */ -	u32        rx_id:16;	/* rx-id */ -	u32        ro;		/* relative offset */ -	u32        r_ctl:8;		/* R_CTL for I.U. */ -	u32        res:24; -}; - - -/*   * FCP_CMND definitions   */  #define FCP_CMND_CDB_LEN    16  #define FCP_CMND_LUN_LEN    8  struct fcp_cmnd_s { -	lun_t           lun;		/* 64-bit LU number */ -	u8         crn;		/* command reference number */ -#ifdef __BIGENDIAN -	u8         resvd:1, +	struct scsi_lun	lun;		/* 64-bit LU number */ +	u8		crn;		/* command reference number */ +#ifdef __BIG_ENDIAN +	u8		resvd:1,  			priority:4,	/* FCP-3: SAM-3 priority */  			taskattr:3;	/* scsi task attribute */  #else -	u8         taskattr:3,	/* scsi task attribute */ +	u8		taskattr:3,	/* scsi task attribute */  			priority:4,	/* FCP-3: SAM-3 priority */  			resvd:1;  #endif -	u8         tm_flags;	/* task management flags */ -#ifdef __BIGENDIAN -	u8         addl_cdb_len:6,	/* additional CDB length words */ +	u8		tm_flags;	/* task management flags */ +#ifdef __BIG_ENDIAN +	u8		addl_cdb_len:6,	/* additional CDB length words */  			iodir:2;	/* read/write FCP_DATA IUs */  #else -	u8         iodir:2,	/* read/write FCP_DATA IUs */ +	u8		iodir:2,	/* read/write FCP_DATA IUs */  			addl_cdb_len:6;	/* additional CDB length */  #endif -	scsi_cdb_t      cdb; +	struct scsi_cdb_s      cdb; -	/* -	 * !!! additional cdb bytes follows here!!! -	 */ -	u32        fcp_dl;	/* bytes to be transferred */ +	__be32        fcp_dl;	/* bytes to be transferred */  };  #define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN) @@ -1210,21 +1091,10 @@ struct fcp_cmnd_s {   * struct fcp_cmnd_s .iodir field values   */  enum fcp_iodir { -	FCP_IODIR_NONE	= 0, +	FCP_IODIR_NONE  = 0,  	FCP_IODIR_WRITE = 1, -	FCP_IODIR_READ	= 2, -	FCP_IODIR_RW	= 3, -}; - -/* - * Task attribute field - */ -enum { -	FCP_TASK_ATTR_SIMPLE	= 0, -	FCP_TASK_ATTR_HOQ	= 1, -	FCP_TASK_ATTR_ORDERED	= 2, -	FCP_TASK_ATTR_ACA	= 4, -	FCP_TASK_ATTR_UNTAGGED	= 5,	/* obsolete in FCP-3 */ +	FCP_IODIR_READ  = 2, +	FCP_IODIR_RW    = 3,  };  /* @@ -1239,58 +1109,40 @@ enum fcp_tm_cmnd {  };  /* - * FCP_XFER_RDY IU defines - */ -struct fcp_xfer_rdy_s { -	u32        data_ro; -	u32        burst_len; -	u32        reserved; -}; - -/*   * FCP_RSP residue flags   */  enum fcp_residue { -	FCP_NO_RESIDUE = 0,	/* no residue */ -	FCP_RESID_OVER = 1,	/* more data left that was not sent */ -	FCP_RESID_UNDER = 2,	/* less data than requested */ -}; - -enum { -	FCP_RSPINFO_GOOD = 0, -	FCP_RSPINFO_DATALEN_MISMATCH = 1, -	FCP_RSPINFO_CMND_INVALID = 2, -	FCP_RSPINFO_ROLEN_MISMATCH = 3, -	FCP_RSPINFO_TM_NOT_SUPP = 4, -	FCP_RSPINFO_TM_FAILED = 5, +	FCP_NO_RESIDUE = 0,     /* no residue */ +	FCP_RESID_OVER = 1,     /* more data left that was not sent */ +	FCP_RESID_UNDER = 2,    /* less data than requested */  };  struct fcp_rspinfo_s {  	u32        res0:24; -	u32        rsp_code:8;	/* response code (as above) */ +	u32        rsp_code:8;		/* response code (as above) */  	u32        res1;  };  struct fcp_resp_s { -	u32        reserved[2];	/* 2 words reserved */ +	u32        reserved[2];		/* 2 words reserved */  	u16        reserved2; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u8         reserved3:3;  	u8         fcp_conf_req:1;	/* FCP_CONF is requested */  	u8         resid_flags:2;	/* underflow/overflow */ -	u8         sns_len_valid:1;/* sense len is valid */ -	u8         rsp_len_valid:1;/* response len is valid */ +	u8         sns_len_valid:1;	/* sense len is valid */ +	u8         rsp_len_valid:1;	/* response len is valid */  #else -	u8         rsp_len_valid:1;/* response len is valid */ -	u8         sns_len_valid:1;/* sense len is valid */ +	u8         rsp_len_valid:1;	/* response len is valid */ +	u8         sns_len_valid:1;	/* sense len is valid */  	u8         resid_flags:2;	/* underflow/overflow */  	u8         fcp_conf_req:1;	/* FCP_CONF is requested */  	u8         reserved3:3;  #endif -	u8         scsi_status;	/* one byte SCSI status */ -	u32        residue;	/* residual data bytes */ -	u32        sns_len;	/* length od sense info */ -	u32        rsp_len;	/* length of response info */ +	u8         scsi_status;		/* one byte SCSI status */ +	u32        residue;		/* residual data bytes */ +	u32        sns_len;		/* length od sense info */ +	u32        rsp_len;		/* length of response info */  };  #define fcp_snslen(__fcprsp)	((__fcprsp)->sns_len_valid ?		\ @@ -1300,12 +1152,6 @@ struct fcp_resp_s {  #define fcp_rspinfo(__fcprsp)	((struct fcp_rspinfo_s *)((__fcprsp) + 1))  #define fcp_snsinfo(__fcprsp)	(((u8 *)fcp_rspinfo(__fcprsp)) +	\  						fcp_rsplen(__fcprsp)) - -struct fcp_cmnd_fr_s { -	struct fchs_s fchs; -	struct fcp_cmnd_s fcp; -}; -  /*   * CT   */ @@ -1379,7 +1225,7 @@ enum {  	CT_RSN_LOGICAL_BUSY	= 0x05,  	CT_RSN_PROTO_ERR	= 0x07,  	CT_RSN_UNABLE_TO_PERF	= 0x09, -	CT_RSN_NOT_SUPP			= 0x0B, +	CT_RSN_NOT_SUPP		= 0x0B,  	CT_RSN_SERVER_NOT_AVBL  = 0x0D,  	CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,  	CT_RSN_VENDOR_SPECIFIC  = 0xFF, @@ -1419,10 +1265,10 @@ enum {   * defintions for the explanation code for all servers   */  enum { -	CT_EXP_AUTH_EXCEPTION			= 0xF1, -	CT_EXP_DB_FULL					= 0xF2, -	CT_EXP_DB_EMPTY					= 0xF3, -	CT_EXP_PROCESSING_REQ			= 0xF4, +	CT_EXP_AUTH_EXCEPTION		= 0xF1, +	CT_EXP_DB_FULL			= 0xF2, +	CT_EXP_DB_EMPTY			= 0xF3, +	CT_EXP_PROCESSING_REQ		= 0xF4,  	CT_EXP_UNABLE_TO_VERIFY_CONN	= 0xF5,  	CT_EXP_DEVICES_NOT_IN_CMN_ZONE  = 0xF6  }; @@ -1438,6 +1284,7 @@ enum {  	GS_GSPN_ID	= 0x0118,	/* Get symbolic PN on ID */  	GS_RFT_ID	= 0x0217,	/* Register fc4type on ID */  	GS_RSPN_ID	= 0x0218,	/* Register symbolic PN on ID */ +	GS_RSNN_NN	= 0x0239,	/* Register symbolic NN on NN */  	GS_RPN_ID	= 0x0212,	/* Register port name */  	GS_RNN_ID	= 0x0213,	/* Register node name */  	GS_RCS_ID	= 0x0214,	/* Register class of service */ @@ -1446,7 +1293,7 @@ enum {  	GS_RFF_ID	= 0x021F,	/* Register FC4 Feature		*/  }; -struct fcgs_id_req_s{ +struct fcgs_id_req_s {  	u32 rsvd:8;  	u32 dap:24; /* port identifier */  }; @@ -1460,7 +1307,7 @@ struct fcgs_gidpn_req_s {  struct fcgs_gidpn_resp_s {  	u32	rsvd:8; -	u32	dap:24;	/* port identifier */ +	u32	dap:24;		/* port identifier */  };  /* @@ -1469,22 +1316,21 @@ struct fcgs_gidpn_resp_s {  struct fcgs_rftid_req_s {  	u32	rsvd:8;  	u32	dap:24;		/* port identifier */ -	u32	fc4_type[8];	/* fc4 types */ +	__be32	fc4_type[8];	/* fc4 types */  };  /*   * RFF_ID : Register FC4 features.   */ -  #define FC_GS_FCP_FC4_FEATURE_INITIATOR  0x02  #define FC_GS_FCP_FC4_FEATURE_TARGET	 0x01  struct fcgs_rffid_req_s { -    u32    rsvd:8; -    u32    dap:24;		/* port identifier	*/ -    u32    rsvd1:16; -    u32    fc4ftr_bits:8;		/* fc4 feature bits	*/ -    u32    fc4_type:8;		/* corresponding FC4 Type */ +	u32	rsvd:8; +	u32	dap:24;		/* port identifier */ +	u32	rsvd1:16; +	u32	fc4ftr_bits:8;	/* fc4 feature bits */ +	u32	fc4_type:8;		/* corresponding FC4 Type */  };  /* @@ -1495,16 +1341,16 @@ struct fcgs_gidft_req_s {  	u8	domain_id;	/* domain, 0 - all fabric */  	u8	area_id;	/* area, 0 - whole domain */  	u8	fc4_type;	/* FC_TYPE_FCP for SCSI devices */ -};		/* GID_FT Request */ +};  /*   * GID_FT Response   */  struct fcgs_gidft_resp_s { -	u8		last:1;	/* last port identifier flag */ -	u8		reserved:7; -	u32	pid:24;	/* port identifier */ -};		/* GID_FT Response */ +	u8	last:1;		/* last port identifier flag */ +	u8	reserved:7; +	u32	pid:24;		/* port identifier */ +};  /*   * RSPN_ID @@ -1512,8 +1358,17 @@ struct fcgs_gidft_resp_s {  struct fcgs_rspnid_req_s {  	u32	rsvd:8;  	u32	dap:24;		/* port identifier */ -	u8		spn_len;	/* symbolic port name length */ -	u8		spn[256];	/* symbolic port name */ +	u8	spn_len;	/* symbolic port name length */ +	u8	spn[256];	/* symbolic port name */ +}; + +/* + * RSNN_NN + */ +struct fcgs_rsnn_nn_req_s { +	wwn_t	node_name;	/* Node name */ +	u8	snn_len;	/* symbolic node name length */ +	u8	snn[256];	/* symbolic node name */  };  /* @@ -1522,7 +1377,7 @@ struct fcgs_rspnid_req_s {  struct fcgs_rpnid_req_s {  	u32	rsvd:8;  	u32	port_id:24; -	wwn_t		port_name; +	wwn_t	port_name;  };  /* @@ -1531,7 +1386,7 @@ struct fcgs_rpnid_req_s {  struct fcgs_rnnid_req_s {  	u32	rsvd:8;  	u32	port_id:24; -	wwn_t		node_name; +	wwn_t	node_name;  };  /* @@ -1565,8 +1420,8 @@ struct fcgs_ganxt_req_s {   * GA_NXT Response   */  struct fcgs_ganxt_rsp_s { -	u32	port_type:8;	/* Port Type */ -	u32	port_id:24;	/* Port Identifier */ +	u32		port_type:8;	/* Port Type */ +	u32		port_id:24;	/* Port Identifier */  	wwn_t		port_name;	/* Port Name */  	u8		spn_len;	/* Length of Symbolic Port Name */  	char		spn[255];	/* Symbolic Port Name */ @@ -1575,19 +1430,14 @@ struct fcgs_ganxt_rsp_s {  	char		snn[255];	/* Symbolic Node Name */  	u8		ipa[8];		/* Initial Process Associator */  	u8		ip[16];		/* IP Address */ -	u32	cos;		/* Class of Service */ -	u32	fc4types[8];	/* FC-4 TYPEs */ -	wwn_t		fabric_port_name; -					/* Fabric Port Name */ -	u32	rsvd:8;		/* Reserved */ -	u32	hard_addr:24;	/* Hard Address */ +	u32		cos;		/* Class of Service */ +	u32		fc4types[8];	/* FC-4 TYPEs */ +	wwn_t		fabric_port_name; /* Fabric Port Name */ +	u32		rsvd:8;		/* Reserved */ +	u32		hard_addr:24;	/* Hard Address */  };  /* - * Fabric Config Server - */ - -/*   * Command codes for Fabric Configuration Server   */  enum { @@ -1598,159 +1448,9 @@ enum {  };  /* - * Source or Destination Port Tags. - */ -enum { -	GS_FTRACE_TAG_NPORT_ID		= 1, -	GS_FTRACE_TAG_NPORT_NAME	= 2, -}; - -/* -* Port Value : Could be a Port id or wwn - */ -union fcgs_port_val_u { -	u32	nport_id; -	wwn_t		nport_wwn; -}; - -#define GS_FTRACE_MAX_HOP_COUNT	20 -#define GS_FTRACE_REVISION	1 - -/* - * Ftrace Related Structures. - */ - -/* - * STR (Switch Trace) Reject Reason Codes. From FC-SW. - */ -enum { -	GS_FTRACE_STR_CMD_COMPLETED_SUCC	= 0, -	GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH, -	GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH, -	GS_FTRACE_STR_MAX_HOP_CNT_REACHED, -	GS_FTRACE_STR_SRC_PORT_NOT_FOUND, -	GS_FTRACE_STR_DST_PORT_NOT_FOUND, -	GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE, -	GS_FTRACE_STR_NO_ROUTE_BW_PORTS, -	GS_FTRACE_STR_NO_ADDL_EXPLN, -	GS_FTRACE_STR_FABRIC_BUSY, -	GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS, -	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0, -	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff, -}; - -/* - * Ftrace Request - */ -struct fcgs_ftrace_req_s { -	u32	revision; -	u16	src_port_tag;	/* Source Port tag */ -	u16	src_port_len;	/* Source Port len */ -	union fcgs_port_val_u src_port_val;	/* Source Port value */ -	u16	dst_port_tag;	/* Destination Port tag */ -	u16	dst_port_len;	/* Destination Port len */ -	union fcgs_port_val_u dst_port_val;	/* Destination Port value */ -	u32	token; -	u8		vendor_id[8];	/* T10 Vendor Identifier */ -	u8		vendor_info[8];	/* Vendor specific Info */ -	u32	max_hop_cnt;	/* Max Hop Count */ -}; - -/* - * Path info structure - */ -struct fcgs_ftrace_path_info_s { -	wwn_t		switch_name;		/* Switch WWN */ -	u32	domain_id; -	wwn_t		ingress_port_name;	/* Ingress ports wwn */ -	u32	ingress_phys_port_num;	/* Ingress ports physical port -						 * number -						 */ -	wwn_t		egress_port_name;	/* Ingress ports wwn */ -	u32	egress_phys_port_num;	/* Ingress ports physical port -						 * number -						 */ -}; - -/* - * Ftrace Acc Response - */ -struct fcgs_ftrace_resp_s { -	u32	revision; -	u32	token; -	u8		vendor_id[8];		/* T10 Vendor Identifier */ -	u8		vendor_info[8];		/* Vendor specific Info */ -	u32	str_rej_reason_code;	/* STR Reject Reason Code */ -	u32	num_path_info_entries;	/* No. of path info entries */ -	/* -	 * path info entry/entries. -	 */ -	struct fcgs_ftrace_path_info_s path_info[1]; - -}; - -/* -* Fabric Config Server : FCPing - */ - -/* - * FC Ping Request - */ -struct fcgs_fcping_req_s { -	u32	revision; -	u16	port_tag; -	u16	port_len;	/* Port len */ -	union fcgs_port_val_u port_val;	/* Port value */ -	u32	token; -}; - -/* - * FC Ping Response - */ -struct fcgs_fcping_resp_s { -	u32	token; -}; - -/* - * Command codes for zone server query. - */ -enum { -	ZS_GZME = 0x0124,	/* Get zone member extended */ -}; - -/* - * ZS GZME request - */ -#define ZS_GZME_ZNAMELEN	32 -struct zs_gzme_req_s { -	u8	znamelen; -	u8	rsvd[3]; -	u8	zname[ZS_GZME_ZNAMELEN]; -}; - -enum zs_mbr_type { -	ZS_MBR_TYPE_PWWN	= 1, -	ZS_MBR_TYPE_DOMPORT	= 2, -	ZS_MBR_TYPE_PORTID	= 3, -	ZS_MBR_TYPE_NWWN	= 4, -}; - -struct zs_mbr_wwn_s { -	u8	mbr_type; -	u8	rsvd[3]; -	wwn_t	wwn; -}; - -struct zs_query_resp_s { -	u32	nmbrs;	/*  number of zone members */ -	struct zs_mbr_wwn_s	mbr[1]; -}; - -/*   * GMAL Command ( Get ( interconnect Element) Management Address List)   * To retrieve the IP Address of a Switch.   */ -  #define CT_GMAL_RESP_PREFIX_TELNET	 "telnet://"  #define CT_GMAL_RESP_PREFIX_HTTP	 "http://" @@ -1764,7 +1464,7 @@ struct fcgs_req_s {  /* Accept Response to GMAL */  struct fcgs_gmal_resp_s { -	u32	ms_len;   /* Num of entries */ +	__be32	ms_len;   /* Num of entries */  	u8	ms_ma[256];  }; @@ -1775,9 +1475,6 @@ struct fcgs_gmal_entry_s {  };  /* - * FDMI - */ -/*   * FDMI Command Codes   */  #define	FDMI_GRHL		0x0100 @@ -1834,6 +1531,12 @@ enum fdmi_hba_attribute_type {  	FDMI_HBA_ATTRIB_FW_VERSION,	/* 0x0009 */  	FDMI_HBA_ATTRIB_OS_NAME,	/* 0x000A */  	FDMI_HBA_ATTRIB_MAX_CT,		/* 0x000B */ +	FDMI_HBA_ATTRIB_NODE_SYM_NAME,  /* 0x000C */ +	FDMI_HBA_ATTRIB_VENDOR_INFO,    /* 0x000D */ +	FDMI_HBA_ATTRIB_NUM_PORTS,  /* 0x000E */ +	FDMI_HBA_ATTRIB_FABRIC_NAME,    /* 0x000F */ +	FDMI_HBA_ATTRIB_BIOS_VER,   /* 0x0010 */ +	FDMI_HBA_ATTRIB_VENDOR_ID = 0x00E0,  	FDMI_HBA_ATTRIB_MAX_TYPE  }; @@ -1848,6 +1551,15 @@ enum fdmi_port_attribute_type {  	FDMI_PORT_ATTRIB_FRAME_SIZE,	/* 0x0004 */  	FDMI_PORT_ATTRIB_DEV_NAME,	/* 0x0005 */  	FDMI_PORT_ATTRIB_HOST_NAME,	/* 0x0006 */ +	FDMI_PORT_ATTRIB_NODE_NAME,     /* 0x0007 */ +	FDMI_PORT_ATTRIB_PORT_NAME,     /* 0x0008 */ +	FDMI_PORT_ATTRIB_PORT_SYM_NAME, /* 0x0009 */ +	FDMI_PORT_ATTRIB_PORT_TYPE,     /* 0x000A */ +	FDMI_PORT_ATTRIB_SUPP_COS,      /* 0x000B */ +	FDMI_PORT_ATTRIB_PORT_FAB_NAME, /* 0x000C */ +	FDMI_PORT_ATTRIB_PORT_FC4_TYPE, /* 0x000D */ +	FDMI_PORT_ATTRIB_PORT_STATE = 0x101,    /* 0x0101 */ +	FDMI_PORT_ATTRIB_PORT_NUM_RPRT = 0x102, /* 0x0102 */  	FDMI_PORT_ATTR_MAX_TYPE  }; @@ -1856,8 +1568,8 @@ enum fdmi_port_attribute_type {   * FDMI attribute   */  struct fdmi_attr_s { -	u16        type; -	u16        len; +	__be16        type; +	__be16        len;  	u8         value[1];  }; @@ -1865,7 +1577,7 @@ struct fdmi_attr_s {   * HBA Attribute Block   */  struct fdmi_hba_attr_s { -	u32        attr_count;	/* # of attributes */ +	__be32        attr_count;	/* # of attributes */  	struct fdmi_attr_s hba_attr;	/* n attributes */  }; @@ -1873,15 +1585,15 @@ struct fdmi_hba_attr_s {   * Registered Port List   */  struct fdmi_port_list_s { -	u32        num_ports;	/* number Of Port Entries */ -	wwn_t           port_entry;	/* one or more */ +	__be32		num_ports;	/* number Of Port Entries */ +	wwn_t		port_entry;	/* one or more */  };  /*   * Port Attribute Block   */  struct fdmi_port_attr_s { -	u32        attr_count;	/* # of attributes */ +	__be32        attr_count;	/* # of attributes */  	struct fdmi_attr_s port_attr;	/* n attributes */  }; @@ -1889,7 +1601,7 @@ struct fdmi_port_attr_s {   * FDMI Register HBA Attributes   */  struct fdmi_rhba_s { -	wwn_t           hba_id;		/* HBA Identifier */ +	wwn_t			hba_id;		/* HBA Identifier */  	struct fdmi_port_list_s port_list;	/* Registered Port List */  	struct fdmi_hba_attr_s hba_attr_blk;	/* HBA attribute block */  }; @@ -1898,8 +1610,8 @@ struct fdmi_rhba_s {   * FDMI Register Port   */  struct fdmi_rprt_s { -	wwn_t           hba_id;		/* HBA Identifier */ -	wwn_t           port_name;	/* Port wwn */ +	wwn_t			hba_id;		/* HBA Identifier */ +	wwn_t			port_name;	/* Port wwn */  	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */  }; @@ -1907,7 +1619,7 @@ struct fdmi_rprt_s {   * FDMI Register Port Attributes   */  struct fdmi_rpa_s { -	wwn_t           port_name;	/* port wwn */ +	wwn_t			port_name;	/* port wwn */  	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */  }; diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c index 9c725314b51..dce787f6cca 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.c +++ b/drivers/scsi/bfa/bfa_fcbuild.c @@ -18,16 +18,16 @@   * fcbuild.c - FC link service frame building and parsing routines   */ -#include "bfa_os_inc.h" +#include "bfad_drv.h"  #include "bfa_fcbuild.h"  /*   * static build functions   */  static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, -				 u16 ox_id); +				 __be16 ox_id);  static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, -				 u16 ox_id); +				 __be16 ox_id);  static struct fchs_s fc_els_req_tmpl;  static struct fchs_s fc_els_rsp_tmpl;  static struct fchs_s fc_bls_req_tmpl; @@ -48,7 +48,7 @@ fcbuild_init(void)  	fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;  	fc_els_req_tmpl.type = FC_TYPE_ELS;  	fc_els_req_tmpl.f_ctl = -		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | +		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |  			      FCTL_SI_XFER);  	fc_els_req_tmpl.rx_id = FC_RXID_ANY; @@ -59,7 +59,7 @@ fcbuild_init(void)  	fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;  	fc_els_rsp_tmpl.type = FC_TYPE_ELS;  	fc_els_rsp_tmpl.f_ctl = -		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | +		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |  			      FCTL_END_SEQ | FCTL_SI_XFER);  	fc_els_rsp_tmpl.rx_id = FC_RXID_ANY; @@ -68,7 +68,7 @@ fcbuild_init(void)  	 */  	fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;  	fc_bls_req_tmpl.type = FC_TYPE_BLS; -	fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER); +	fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);  	fc_bls_req_tmpl.rx_id = FC_RXID_ANY;  	/* @@ -78,7 +78,7 @@ fcbuild_init(void)  	fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;  	fc_bls_rsp_tmpl.type = FC_TYPE_BLS;  	fc_bls_rsp_tmpl.f_ctl = -		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | +		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |  			      FCTL_END_SEQ | FCTL_SI_XFER);  	fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY; @@ -94,7 +94,6 @@ fcbuild_init(void)  	 */  	plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;  	plogi_tmpl.csp.verlo = FC_PH_VER_4_3; -	plogi_tmpl.csp.bbcred = cpu_to_be16(0x0004);  	plogi_tmpl.csp.ciro = 0x1;  	plogi_tmpl.csp.cisc = 0x0;  	plogi_tmpl.csp.altbbcred = 0x0; @@ -129,7 +128,7 @@ fcbuild_init(void)  	fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;  	fcp_fchs_tmpl.type = FC_TYPE_FCP;  	fcp_fchs_tmpl.f_ctl = -		bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); +		bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);  	fcp_fchs_tmpl.seq_id = 1;  	fcp_fchs_tmpl.rx_id = FC_RXID_ANY;  } @@ -143,7 +142,7 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)  	fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;  	fchs->type = FC_TYPE_SERVICES;  	fchs->f_ctl = -		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | +		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |  			      FCTL_SI_XFER);  	fchs->rx_id = FC_RXID_ANY;  	fchs->d_id = (d_id); @@ -156,8 +155,24 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)  	 */  } +static void +fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) +{ +	memset(fchs, 0, sizeof(struct fchs_s)); + +	fchs->routing = FC_RTG_FC4_DEV_DATA; +	fchs->cat_info = FC_CAT_SOLICIT_CTRL; +	fchs->type = FC_TYPE_SERVICES; +	fchs->f_ctl = +		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | +			   FCTL_END_SEQ | FCTL_SI_XFER); +	fchs->d_id = d_id; +	fchs->s_id = s_id; +	fchs->ox_id = ox_id; +} +  void -fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) +fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)  {  	memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));  	fchs->d_id = (d_id); @@ -166,7 +181,7 @@ fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)  }  static void -fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) +fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)  {  	memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));  	fchs->d_id = d_id; @@ -196,7 +211,7 @@ fc_els_rsp_parse(struct fchs_s *fchs, int len)  }  static void -fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) +fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)  {  	memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));  	fchs->d_id = d_id; @@ -206,13 +221,17 @@ fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)  static          u16  fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, -		 u16 ox_id, wwn_t port_name, wwn_t node_name, -		 u16 pdu_size, u8 els_code) +		 __be16 ox_id, wwn_t port_name, wwn_t node_name, +		 u16 pdu_size, u16 bb_cr, u8 els_code)  {  	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);  	memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s)); +	/* For FC AL bb_cr is 0 and altbbcred is 1 */ +	if (!bb_cr) +		plogi->csp.altbbcred = 1; +  	plogi->els_cmd.els_code = els_code;  	if (els_code == FC_ELS_PLOGI)  		fc_els_req_build(fchs, d_id, s_id, ox_id); @@ -220,6 +239,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,  		fc_els_rsp_build(fchs, d_id, s_id, ox_id);  	plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size); +	plogi->csp.bbcred  = cpu_to_be16(bb_cr);  	memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));  	memcpy(&plogi->node_name, &node_name, sizeof(wwn_t)); @@ -232,8 +252,8 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,  		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,  	       u8 set_npiv, u8 set_auth, u16 local_bb_credits)  { -	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT); -	u32	*vvl_info; +	u32        d_id = bfa_hton3b(FC_FABRIC_PORT); +	__be32	*vvl_info;  	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); @@ -267,16 +287,18 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,  u16  fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, -		   u16 ox_id, wwn_t port_name, wwn_t node_name, -		   u16 pdu_size, u16 local_bb_credits) +		   __be16 ox_id, wwn_t port_name, wwn_t node_name, +		   u16 pdu_size, u16 local_bb_credits, u8 bb_scn)  {  	u32        d_id = 0; +	u16	   bbscn_rxsz = (bb_scn << 12) | pdu_size;  	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));  	fc_els_rsp_build(fchs, d_id, s_id, ox_id);  	flogi->els_cmd.els_code = FC_ELS_ACC; -	flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size); +	flogi->class3.rxsz = cpu_to_be16(pdu_size); +	flogi->csp.rxsz  = cpu_to_be16(bbscn_rxsz);	/* bb_scn/rxsz */  	flogi->port_name = port_name;  	flogi->node_name = node_name; @@ -289,7 +311,7 @@ u16  fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,  		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)  { -	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT); +	u32        d_id = bfa_hton3b(FC_FABRIC_PORT);  	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); @@ -306,19 +328,19 @@ fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,  u16  fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,  	       u16 ox_id, wwn_t port_name, wwn_t node_name, -	       u16 pdu_size) +	       u16 pdu_size, u16 bb_cr)  {  	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, -				node_name, pdu_size, FC_ELS_PLOGI); +				node_name, pdu_size, bb_cr, FC_ELS_PLOGI);  }  u16  fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,  		   u16 ox_id, wwn_t port_name, wwn_t node_name, -		   u16 pdu_size) +		   u16 pdu_size, u16 bb_cr)  {  	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, -				node_name, pdu_size, FC_ELS_ACC); +				node_name, pdu_size, bb_cr, FC_ELS_ACC);  }  enum fc_parse_status @@ -392,7 +414,7 @@ fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,  u16  fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, -		  u16 ox_id, enum bfa_lport_role role) +		  __be16 ox_id, enum bfa_lport_role role)  {  	struct fc_prli_s *prli = (struct fc_prli_s *) (pld); @@ -456,9 +478,9 @@ fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,  	return sizeof(struct fc_logo_s);  } -static          u16 +static u16  fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, -		 u32 s_id, u16 ox_id, wwn_t port_name, +		 u32 s_id, __be16 ox_id, wwn_t port_name,  		 wwn_t node_name, u8 els_code)  {  	memset(adisc, '\0', sizeof(struct fc_adisc_s)); @@ -480,7 +502,7 @@ fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,  u16  fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, -		u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name) +		u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)  {  	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,  				node_name, FC_ELS_ADISC); @@ -488,7 +510,7 @@ fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,  u16  fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, -		   u32 s_id, u16 ox_id, wwn_t port_name, +		   u32 s_id, __be16 ox_id, wwn_t port_name,  		   wwn_t node_name)  {  	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, @@ -592,7 +614,7 @@ fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,  u16  fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, -		  u16 ox_id) +		  __be16 ox_id)  {  	struct fc_els_cmd_s *acc = pld; @@ -606,7 +628,7 @@ fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,  u16  fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id, -		u32 s_id, u16 ox_id, u8 reason_code, +		u32 s_id, __be16 ox_id, u8 reason_code,  		u8 reason_code_expl)  {  	fc_els_rsp_build(fchs, d_id, s_id, ox_id); @@ -622,7 +644,7 @@ fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,  u16  fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, -		u32 s_id, u16 ox_id, u16 rx_id) +		u32 s_id, __be16 ox_id, u16 rx_id)  {  	fc_bls_rsp_build(fchs, d_id, s_id, ox_id); @@ -638,7 +660,7 @@ fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,  u16  fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id, -		u32 s_id, u16 ox_id) +		u32 s_id, __be16 ox_id)  {  	fc_els_rsp_build(fchs, d_id, s_id, ox_id);  	memset(els_cmd, 0, sizeof(struct fc_els_cmd_s)); @@ -666,7 +688,7 @@ fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)  u16  fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, -		u32 d_id, u32 s_id, u16 ox_id, int num_pages) +		u32 d_id, u32 s_id, __be16 ox_id, int num_pages)  {  	int             page; @@ -690,7 +712,7 @@ fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,  u16  fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id, -		  u32 s_id, u16 ox_id, int num_pages) +		  u32 s_id, __be16 ox_id, int num_pages)  {  	int             page; @@ -728,7 +750,7 @@ fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,  u16  fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id, -		  u32 s_id, u16 ox_id, u32 data_format, +		  u32 s_id, __be16 ox_id, u32 data_format,  		  struct fc_rnid_common_id_data_s *common_id_data,  		  struct fc_rnid_general_topology_data_s *gen_topo_data)  { @@ -770,10 +792,10 @@ u16  fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,  		u32 s_id, u32 *pid_list, u16 npids)  { -	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id)); +	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));  	int i = 0; -	fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0); +	fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);  	memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s)); @@ -788,7 +810,7 @@ fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,  u16  fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, -		u32 d_id, u32 s_id, u16 ox_id, +		u32 d_id, u32 s_id, __be16 ox_id,  		  struct fc_rpsc_speed_info_s *oper_speed)  {  	memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s)); @@ -807,11 +829,6 @@ fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,  	return sizeof(struct fc_rpsc_acc_s);  } -/* - * TBD - - * . get rid of unnecessary memsets - */ -  u16  fc_logo_rsp_parse(struct fchs_s *fchs, int len)  { @@ -995,7 +1012,7 @@ fc_rrq_rsp_parse(struct fchs_s *fchs, int len)  }  u16 -fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, +fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,  		u32 reason_code, u32 reason_expl)  {  	struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1); @@ -1045,7 +1062,7 @@ fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);  	fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN); @@ -1061,7 +1078,7 @@ fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);  	fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID); @@ -1077,7 +1094,7 @@ fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);  	fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID); @@ -1101,10 +1118,25 @@ fc_ct_rsp_parse(struct ct_hdr_s *cthdr)  }  u16 +fc_gs_rjt_build(struct fchs_s *fchs,  struct ct_hdr_s *cthdr, +		u32 d_id, u32 s_id, u16 ox_id, u8 reason_code, +		u8 reason_code_expl) +{ +	fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id); + +	cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT); +	cthdr->rev_id = CT_GS3_REVISION; + +	cthdr->reason_code = reason_code; +	cthdr->exp_code    = reason_code_expl; +	return sizeof(struct ct_hdr_s); +} + +u16  fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,  		u8 set_br_reg, u32 s_id, u16 ox_id)  { -	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); +	u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);  	fc_els_req_build(fchs, d_id, s_id, ox_id); @@ -1121,7 +1153,7 @@ u16  fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,  		u32 s_id, u16 ox_id)  { -	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); +	u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);  	u16        payldlen;  	fc_els_req_build(fchs, d_id, s_id, ox_id); @@ -1143,7 +1175,7 @@ fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); -	u32        type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        type_value, d_id = bfa_hton3b(FC_NAME_SERVER);  	u8         index;  	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); @@ -1167,7 +1199,7 @@ fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);  	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); @@ -1187,7 +1219,7 @@ fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1); -	u32         d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32         d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);  	fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID); @@ -1209,7 +1241,7 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rspnid_req_s *rspnid =  			(struct fcgs_rspnid_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);  	fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID); @@ -1224,12 +1256,33 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  }  u16 +fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id, +			wwn_t node_name, u8 *name) +{ +	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; +	struct fcgs_rsnn_nn_req_s *rsnn_nn = +		(struct fcgs_rsnn_nn_req_s *) (cthdr + 1); +	u32	d_id = bfa_hton3b(FC_NAME_SERVER); + +	fc_gs_fchdr_build(fchs, d_id, s_id, 0); +	fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN); + +	memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s)); + +	rsnn_nn->node_name = node_name; +	rsnn_nn->snn_len = (u8) strlen((char *)name); +	strncpy((char *)rsnn_nn->snn, (char *)name, rsnn_nn->snn_len); + +	return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s); +} + +u16  fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0); @@ -1249,7 +1302,7 @@ fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID); @@ -1267,7 +1320,7 @@ fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID); @@ -1286,7 +1339,7 @@ fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rcsid_req_s *rcsid =  			(struct fcgs_rcsid_req_s *) (cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID); @@ -1304,7 +1357,7 @@ fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID); @@ -1321,7 +1374,7 @@ fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER); +	u32        d_id = bfa_hton3b(FC_NAME_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT); @@ -1341,7 +1394,7 @@ fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; -	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER); +	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code); @@ -1356,7 +1409,7 @@ void  fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)  {  	u8         index; -	u32       *ptr = (u32 *) bit_mask; +	__be32       *ptr = (__be32 *) bit_mask;  	u32        type_value;  	/* @@ -1377,7 +1430,7 @@ fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER); +	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD, @@ -1397,7 +1450,7 @@ fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)  {  	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;  	fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1); -	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER); +	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);  	fc_gs_fchdr_build(fchs, d_id, s_id, 0);  	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD, diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h index 73abd02e53c..03c753d1e54 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.h +++ b/drivers/scsi/bfa/bfa_fcbuild.h @@ -21,7 +21,7 @@  #ifndef __FCBUILD_H__  #define __FCBUILD_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h"  #include "bfa_fc.h"  #include "bfa_defs_fcs.h" @@ -66,6 +66,9 @@ fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)  	case RPSC_OP_SPEED_8G:  		return BFA_PORT_SPEED_8GBPS; +	case RPSC_OP_SPEED_16G: +		return BFA_PORT_SPEED_16GBPS; +  	case RPSC_OP_SPEED_10G:  		return BFA_PORT_SPEED_10GBPS; @@ -94,6 +97,9 @@ fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)  	case BFA_PORT_SPEED_8GBPS:  		return RPSC_OP_SPEED_8G; +	case BFA_PORT_SPEED_16GBPS: +		return RPSC_OP_SPEED_16G; +  	case BFA_PORT_SPEED_10GBPS:  		return RPSC_OP_SPEED_10G; @@ -138,14 +144,14 @@ u16        fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id,  			       u16 pdu_size);  u16        fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, -				   u32 s_id, u16 ox_id, +				   u32 s_id, __be16 ox_id,  				   wwn_t port_name, wwn_t node_name,  				   u16 pdu_size, -				   u16 local_bb_credits); +				   u16 local_bb_credits, u8 bb_scn);  u16        fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,  			       u32 s_id, u16 ox_id, wwn_t port_name, -			       wwn_t node_name, u16 pdu_size); +			       wwn_t node_name, u16 pdu_size, u16 bb_cr);  enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs); @@ -160,6 +166,8 @@ enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);  u16        fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,  				u16 ox_id, u8 *name); +u16	fc_rsnn_nn_build(struct fchs_s *fchs, void *pld, u32 s_id, +				wwn_t node_name, u8 *name);  u16        fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,  			       u16 ox_id, enum bfa_lport_role role); @@ -177,16 +185,20 @@ u16        fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,  u16        fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,  			       u16 ox_id, u32 port_id); +u16	fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr, +			u32 d_id, u32 s_id, u16 ox_id, +			u8 reason_code, u8 reason_code_expl); +  u16        fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,  			u8 set_br_reg, u32 s_id, u16 ox_id);  u16        fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,  				   u32 s_id, u16 ox_id,  				   wwn_t port_name, wwn_t node_name, -				   u16 pdu_size); +				   u16 pdu_size, u16 bb_cr);  u16        fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, -			u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name, +			u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,  			       wwn_t node_name);  enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld, @@ -196,20 +208,20 @@ enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,  				 wwn_t port_name, wwn_t node_name);  u16        fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, -				   u32 d_id, u32 s_id, u16 ox_id, +				   u32 d_id, u32 s_id, __be16 ox_id,  				   wwn_t port_name, wwn_t node_name);  u16        fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, -				u32 d_id, u32 s_id, u16 ox_id, +				u32 d_id, u32 s_id, __be16 ox_id,  				u8 reason_code, u8 reason_code_expl);  u16        fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, -				u32 d_id, u32 s_id, u16 ox_id); +				u32 d_id, u32 s_id, __be16 ox_id);  u16        fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,  			      u32 s_id, u16 ox_id);  enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);  u16        fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, -				  u32 s_id, u16 ox_id, +				  u32 s_id, __be16 ox_id,  				  enum bfa_lport_role role);  u16        fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, @@ -218,7 +230,7 @@ u16        fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,  u16        fc_rnid_acc_build(struct fchs_s *fchs,  			struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id, -			u16 ox_id, u32 data_format, +			__be16 ox_id, u32 data_format,  			struct fc_rnid_common_id_data_s *common_id_data,  			struct fc_rnid_general_topology_data_s *gen_topo_data); @@ -228,7 +240,7 @@ u16        fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,  			      u32 d_id, u32 s_id, u16 ox_id);  u16        fc_rpsc_acc_build(struct fchs_s *fchs,  			struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id, -			u16 ox_id, struct fc_rpsc_speed_info_s *oper_speed); +			__be16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);  u16        fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,  				u8 fc4_type); @@ -251,7 +263,7 @@ u16        fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,  			      u32 s_id, u16 ox_id, wwn_t port_name);  u16        fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, -				  u32 s_id, u16 ox_id); +				  u32 s_id, __be16 ox_id);  u16        fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,  				     u16 cmd_code); @@ -261,7 +273,7 @@ u16	fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);  void		fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);  void		fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, -					 u16 ox_id); +					 __be16 ox_id);  enum fc_parse_status	fc_els_rsp_parse(struct fchs_s *fchs, int len); @@ -274,15 +286,15 @@ enum fc_parse_status	fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,  					wwn_t port_name);  u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, -		u32 s_id, u16 ox_id, u16 rx_id); +		u32 s_id, __be16 ox_id, u16 rx_id);  int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);  u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, -		u32 d_id, u32 s_id, u16 ox_id, int num_pages); +		u32 d_id, u32 s_id, __be16 ox_id, int num_pages);  u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, -		u32 d_id, u32 s_id, u16 ox_id, int num_pages); +		u32 d_id, u32 s_id, __be16 ox_id, int num_pages);  u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len); @@ -304,7 +316,7 @@ u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,  u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);  u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, -		u16 ox_id, u32 reason_code, u32 reason_expl); +		__be16 ox_id, u32 reason_code, u32 reason_expl);  u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,  		u32 port_id); diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 135c4427801..d7385d1d9c5 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -15,21 +15,16 @@   * General Public License for more details.   */ +#include "bfad_drv.h"  #include "bfa_modules.h" -#include "bfa_cb_ioim.h"  BFA_TRC_FILE(HAL, FCPIM); -BFA_MODULE(fcpim); - - -#define bfa_fcpim_add_iostats(__l, __r, __stats)	\ -	(__l->__stats += __r->__stats) -  /*   *  BFA ITNIM Related definitions   */  static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); +static void bfa_ioim_lm_init(struct bfa_s *bfa);  #define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                                \  	(((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))) @@ -37,12 +32,12 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);  #define bfa_fcpim_additn(__itnim)					\  	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)  #define bfa_fcpim_delitn(__itnim)	do {				\ -	bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \ +	WARN_ON(!bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));   \  	bfa_itnim_update_del_itn_stats(__itnim);      \  	list_del(&(__itnim)->qe);      \ -	bfa_assert(list_empty(&(__itnim)->io_q));      \ -	bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \ -	bfa_assert(list_empty(&(__itnim)->pending_q));      \ +	WARN_ON(!list_empty(&(__itnim)->io_q));				\ +	WARN_ON(!list_empty(&(__itnim)->io_cleanup_q));			\ +	WARN_ON(!list_empty(&(__itnim)->pending_q));			\  } while (0)  #define bfa_itnim_online_cb(__itnim) do {				\ @@ -72,11 +67,14 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);  	}								\  } while (0) +enum bfa_ioim_lm_ua_status { +	BFA_IOIM_LM_UA_RESET = 0, +	BFA_IOIM_LM_UA_SET = 1, +}; +  /* - *  bfa_itnim_sm BFA itnim state machine + *  itnim state machine event   */ - -  enum bfa_itnim_event {  	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */  	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */ @@ -107,9 +105,6 @@ enum bfa_itnim_event {  	if ((__fcpim)->profile_start)					\  		(__fcpim)->profile_start(__ioim);			\  } while (0) -/* - *  hal_ioim_sm - */  /*   * IO state machine events @@ -163,6 +158,7 @@ enum bfa_tskim_event {  	BFA_TSKIM_SM_IOS_DONE	= 7,	/*  IO and sub TM completions	*/  	BFA_TSKIM_SM_CLEANUP	= 8,	/*  TM cleanup on ITN offline	*/  	BFA_TSKIM_SM_CLEANUP_DONE = 9,	/*  TM abort completion	*/ +	BFA_TSKIM_SM_UTAG	= 10,	/*  TM completion unknown tag  */  };  /* @@ -221,8 +217,7 @@ static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,   * forward declaration for BFA IOIM functions   */  static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim); -static bfa_boolean_t	bfa_ioim_sge_setup(struct bfa_ioim_s *ioim); -static void		bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim); +static bfa_boolean_t	bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim);  static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);  static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);  static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete); @@ -232,7 +227,6 @@ static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);  static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);  static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim); -  /*   * forward declaration of BFA IO state machine   */ @@ -260,14 +254,13 @@ static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,  					enum bfa_ioim_event event);  static void	bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,  					enum bfa_ioim_event event); -  /*   * forward declaration for BFA TSKIM functions   */  static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);  static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);  static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim, -					lun_t lun); +					struct scsi_lun lun);  static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);  static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);  static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim); @@ -275,7 +268,6 @@ static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);  static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);  static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim); -  /*   * forward declaration of BFA TSKIM state machine   */ @@ -293,33 +285,24 @@ static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,  					enum bfa_tskim_event event);  static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,  					enum bfa_tskim_event event); -  /* - *  hal_fcpim_mod BFA FCP Initiator Mode module + *  BFA FCP Initiator Mode module   */  /* - *	Compute and return memory needed by FCP(im) module. + * Compute and return memory needed by FCP(im) module.   */  static void -bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -		u32 *dm_len) +bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)  { -	bfa_itnim_meminfo(cfg, km_len, dm_len); +	bfa_itnim_meminfo(cfg, km_len);  	/*  	 * IO memory  	 */ -	if (cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN) -		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN; -	else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX) -		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX; -  	*km_len += cfg->fwcfg.num_ioim_reqs *  	  (sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s)); -	*dm_len += cfg->fwcfg.num_ioim_reqs * BFI_IOIM_SNSLEN; -  	/*  	 * task management command memory  	 */ @@ -330,62 +313,68 @@ bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,  static void -bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) +bfa_fcpim_attach(struct bfa_fcp_mod_s *fcp, void *bfad, +		struct bfa_iocfc_cfg_s *cfg, struct bfa_pcidev_s *pcidev)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = &fcp->fcpim; +	struct bfa_s *bfa = fcp->bfa;  	bfa_trc(bfa, cfg->drvcfg.path_tov);  	bfa_trc(bfa, cfg->fwcfg.num_rports);  	bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);  	bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs); +	fcpim->fcp		= fcp;  	fcpim->bfa		= bfa;  	fcpim->num_itnims	= cfg->fwcfg.num_rports; -	fcpim->num_ioim_reqs  = cfg->fwcfg.num_ioim_reqs;  	fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;  	fcpim->path_tov		= cfg->drvcfg.path_tov;  	fcpim->delay_comp	= cfg->drvcfg.delay_comp;  	fcpim->profile_comp = NULL;  	fcpim->profile_start = NULL; -	bfa_itnim_attach(fcpim, meminfo); -	bfa_tskim_attach(fcpim, meminfo); -	bfa_ioim_attach(fcpim, meminfo); +	bfa_itnim_attach(fcpim); +	bfa_tskim_attach(fcpim); +	bfa_ioim_attach(fcpim);  }  static void -bfa_fcpim_detach(struct bfa_s *bfa) +bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *fcp)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = &fcp->fcpim; +	struct bfa_itnim_s *itnim; +	struct list_head *qe, *qen; -	bfa_ioim_detach(fcpim); -	bfa_tskim_detach(fcpim); -} +	/* Enqueue unused ioim resources to free_q */ +	list_splice_tail_init(&fcpim->tskim_unused_q, &fcpim->tskim_free_q); -static void -bfa_fcpim_start(struct bfa_s *bfa) -{ +	list_for_each_safe(qe, qen, &fcpim->itnim_q) { +		itnim = (struct bfa_itnim_s *) qe; +		bfa_itnim_iocdisable(itnim); +	}  } -static void -bfa_fcpim_stop(struct bfa_s *bfa) +void +bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)  { +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa); + +	fcpim->path_tov = path_tov * 1000; +	if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX) +		fcpim->path_tov = BFA_FCPIM_PATHTOV_MAX;  } -static void -bfa_fcpim_iocdisable(struct bfa_s *bfa) +u16 +bfa_fcpim_path_tov_get(struct bfa_s *bfa)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); -	struct bfa_itnim_s *itnim; -	struct list_head *qe, *qen; +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa); -	list_for_each_safe(qe, qen, &fcpim->itnim_q) { -		itnim = (struct bfa_itnim_s *) qe; -		bfa_itnim_iocdisable(itnim); -	} +	return fcpim->path_tov / 1000;  } +#define bfa_fcpim_add_iostats(__l, __r, __stats)	\ +	(__l->__stats += __r->__stats) +  void  bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,  		struct bfa_itnim_iostats_s *rstats) @@ -436,29 +425,11 @@ bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,  	bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);  } -void -bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov) -{ -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - -	fcpim->path_tov = path_tov * 1000; -	if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX) -		fcpim->path_tov = BFA_FCPIM_PATHTOV_MAX; -} - -u16 -bfa_fcpim_path_tov_get(struct bfa_s *bfa) -{ -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - -	return fcpim->path_tov / 1000; -} -  bfa_status_t -bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats, -	u8 lp_tag) +bfa_fcpim_port_iostats(struct bfa_s *bfa, +		struct bfa_itnim_iostats_s *stats, u8 lp_tag)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct list_head *qe, *qen;  	struct bfa_itnim_s *itnim; @@ -472,39 +443,35 @@ bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats,  	}  	return BFA_STATUS_OK;  } -bfa_status_t -bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *modstats) -{ -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); -	struct list_head *qe, *qen; -	struct bfa_itnim_s *itnim; - -	/* accumulate IO stats from itnim */ -	memset(modstats, 0, sizeof(struct bfa_itnim_iostats_s)); -	list_for_each_safe(qe, qen, &fcpim->itnim_q) { -		itnim = (struct bfa_itnim_s *) qe; -		bfa_fcpim_add_stats(modstats, &(itnim->stats)); -	} -	return BFA_STATUS_OK; -} -bfa_status_t -bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa, -	 struct bfa_fcpim_del_itn_stats_s *modstats) +void +bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_itnim_latency_s *io_lat = +			&(ioim->itnim->ioprofile.io_latency); +	u32 val, idx; -	*modstats = fcpim->del_itn_stats; +	val = (u32)(jiffies - ioim->start_time); +	idx = bfa_ioim_get_index(scsi_bufflen((struct scsi_cmnd *)ioim->dio)); +	bfa_itnim_ioprofile_update(ioim->itnim, idx); -	return BFA_STATUS_OK; +	io_lat->count[idx]++; +	io_lat->min[idx] = (io_lat->min[idx] < val) ? io_lat->min[idx] : val; +	io_lat->max[idx] = (io_lat->max[idx] > val) ? io_lat->max[idx] : val; +	io_lat->avg[idx] += val;  } +void +bfa_ioim_profile_start(struct bfa_ioim_s *ioim) +{ +	ioim->start_time = jiffies; +}  bfa_status_t  bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)  {  	struct bfa_itnim_s *itnim; -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct list_head *qe, *qen;  	/* accumulate IO stats from itnim */ @@ -516,13 +483,13 @@ bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)  	fcpim->io_profile_start_time = time;  	fcpim->profile_comp = bfa_ioim_profile_comp;  	fcpim->profile_start = bfa_ioim_profile_start; -  	return BFA_STATUS_OK;  } +  bfa_status_t  bfa_fcpim_profile_off(struct bfa_s *bfa)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	fcpim->io_profile = BFA_FALSE;  	fcpim->io_profile_start_time = 0;  	fcpim->profile_comp = NULL; @@ -530,86 +497,20 @@ bfa_fcpim_profile_off(struct bfa_s *bfa)  	return BFA_STATUS_OK;  } -bfa_status_t -bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag) -{ -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); -	struct list_head *qe, *qen; -	struct bfa_itnim_s *itnim; - -	/* clear IO stats from all active itnims */ -	list_for_each_safe(qe, qen, &fcpim->itnim_q) { -		itnim = (struct bfa_itnim_s *) qe; -		if (itnim->rport->rport_info.lp_tag != lp_tag) -			continue; -		bfa_itnim_clear_stats(itnim); -	} -	return BFA_STATUS_OK; - -} - -bfa_status_t -bfa_fcpim_clr_modstats(struct bfa_s *bfa) -{ -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); -	struct list_head *qe, *qen; -	struct bfa_itnim_s *itnim; - -	/* clear IO stats from all active itnims */ -	list_for_each_safe(qe, qen, &fcpim->itnim_q) { -		itnim = (struct bfa_itnim_s *) qe; -		bfa_itnim_clear_stats(itnim); -	} -	memset(&fcpim->del_itn_stats, 0, -		sizeof(struct bfa_fcpim_del_itn_stats_s)); - -	return BFA_STATUS_OK; -} - -void -bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth) -{ -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - -	bfa_assert(q_depth <= BFA_IOCFC_QDEPTH_MAX); - -	fcpim->q_depth = q_depth; -} -  u16  bfa_fcpim_qdepth_get(struct bfa_s *bfa)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	return fcpim->q_depth;  } -void -bfa_fcpim_update_ioredirect(struct bfa_s *bfa) -{ -	bfa_boolean_t ioredirect; - -	/* -	 * IO redirection is turned off when QoS is enabled and vice versa -	 */ -	ioredirect = bfa_fcport_is_qos_enabled(bfa) ? BFA_FALSE : BFA_TRUE; -} - -void -bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state) -{ -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); -	fcpim->ioredirect = state; -} - - -  /*   *  BFA ITNIM module state machine functions   */  /* - *	Beginning/unallocated state - no events expected. + * Beginning/unallocated state - no events expected.   */  static void  bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -630,7 +531,7 @@ bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)  }  /* - *	Beginning state, only online event expected. + * Beginning state, only online event expected.   */  static void  bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -733,7 +634,7 @@ bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,  }  /* - *	Waiting for itnim create response from firmware, a delete is pending. + * Waiting for itnim create response from firmware, a delete is pending.   */  static void  bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim, @@ -761,7 +662,7 @@ bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,  }  /* - *	Online state - normal parking state. + * Online state - normal parking state.   */  static void  bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -803,7 +704,7 @@ bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)  }  /* - *	Second level error recovery need. + * Second level error recovery need.   */  static void  bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -834,7 +735,7 @@ bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)  }  /* - *	Going offline. Waiting for active IO cleanup. + * Going offline. Waiting for active IO cleanup.   */  static void  bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim, @@ -871,7 +772,7 @@ bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,  }  /* - *	Deleting itnim. Waiting for active IO cleanup. + * Deleting itnim. Waiting for active IO cleanup.   */  static void  bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim, @@ -956,7 +857,7 @@ bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,  }  /* - *	Offline state. + * Offline state.   */  static void  bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -987,9 +888,6 @@ bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)  	}  } -/* - *	IOC h/w failed state. - */  static void  bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,  				enum bfa_itnim_event event) @@ -1024,7 +922,7 @@ bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,  }  /* - *	Itnim is deleted, waiting for firmware response to delete. + * Itnim is deleted, waiting for firmware response to delete.   */  static void  bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -1069,7 +967,7 @@ bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,  }  /* - *	Initiate cleanup of all IOs on an IOC failure. + * Initiate cleanup of all IOs on an IOC failure.   */  static void  bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim) @@ -1103,7 +1001,7 @@ bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)  }  /* - *	IO cleanup completion + * IO cleanup completion   */  static void  bfa_itnim_cleanp_comp(void *itnim_cbarg) @@ -1115,7 +1013,7 @@ bfa_itnim_cleanp_comp(void *itnim_cbarg)  }  /* - *	Initiate cleanup of all IOs. + * Initiate cleanup of all IOs.   */  static void  bfa_itnim_cleanup(struct bfa_itnim_s *itnim) @@ -1187,9 +1085,6 @@ bfa_itnim_qresume(void *cbarg)  	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);  } - - -  /*   *  bfa_itnim_public   */ @@ -1207,8 +1102,7 @@ bfa_itnim_tskdone(struct bfa_itnim_s *itnim)  }  void -bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -		u32 *dm_len) +bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)  {  	/*  	 * ITN memory @@ -1217,15 +1111,16 @@ bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,  }  void -bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) +bfa_itnim_attach(struct bfa_fcpim_s *fcpim)  {  	struct bfa_s	*bfa = fcpim->bfa; +	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;  	struct bfa_itnim_s *itnim;  	int	i, j;  	INIT_LIST_HEAD(&fcpim->itnim_q); -	itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo); +	itnim = (struct bfa_itnim_s *) bfa_mem_kva_curp(fcp);  	fcpim->itnim_arr = itnim;  	for (i = 0; i < fcpim->num_itnims; i++, itnim++) { @@ -1247,7 +1142,7 @@ bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)  		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);  	} -	bfa_meminfo_kva(minfo) = (u8 *) itnim; +	bfa_mem_kva_curp(fcp) = (u8 *) itnim;  }  void @@ -1260,7 +1155,7 @@ bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)  static bfa_boolean_t  bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)  { -	struct bfi_itnim_create_req_s *m; +	struct bfi_itn_create_req_s *m;  	itnim->msg_no++; @@ -1273,8 +1168,8 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)  		return BFA_FALSE;  	} -	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ, -			bfa_lpuid(itnim->bfa)); +	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_CREATE_REQ, +			bfa_fn_lpu(itnim->bfa));  	m->fw_handle = itnim->rport->fw_handle;  	m->class = FC_CLASS_3;  	m->seq_rec = itnim->seq_rec; @@ -1284,14 +1179,14 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(itnim->bfa, itnim->reqq); +	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);  	return BFA_TRUE;  }  static bfa_boolean_t  bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)  { -	struct bfi_itnim_delete_req_s *m; +	struct bfi_itn_delete_req_s *m;  	/*  	 * check for room in queue to send request now @@ -1302,15 +1197,15 @@ bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)  		return BFA_FALSE;  	} -	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ, -			bfa_lpuid(itnim->bfa)); +	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_DELETE_REQ, +			bfa_fn_lpu(itnim->bfa));  	m->fw_handle = itnim->rport->fw_handle;  	bfa_stats(itnim, fw_delete);  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(itnim->bfa, itnim->reqq); +	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);  	return BFA_TRUE;  } @@ -1401,7 +1296,7 @@ bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)  	if (itnim->fcpim->path_tov > 0) {  		itnim->iotov_active = BFA_TRUE; -		bfa_assert(bfa_itnim_hold_io(itnim)); +		WARN_ON(!bfa_itnim_hold_io(itnim));  		bfa_timer_start(itnim->bfa, &itnim->timer,  			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);  	} @@ -1441,7 +1336,7 @@ bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)  static void  bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);  	fcpim->del_itn_stats.del_itn_iocomp_aborted +=  		itnim->stats.iocomp_aborted;  	fcpim->del_itn_stats.del_itn_iocomp_timedout += @@ -1457,20 +1352,18 @@ bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)  	fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;  } - -  /* - *  bfa_itnim_public + * bfa_itnim_public   */  /* - *	Itnim interrupt processing. + * Itnim interrupt processing.   */  void  bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); -	union bfi_itnim_i2h_msg_u msg; +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa); +	union bfi_itn_i2h_msg_u msg;  	struct bfa_itnim_s *itnim;  	bfa_trc(bfa, m->mhdr.msg_id); @@ -1478,23 +1371,23 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  	msg.msg = m;  	switch (m->mhdr.msg_id) { -	case BFI_ITNIM_I2H_CREATE_RSP: +	case BFI_ITN_I2H_CREATE_RSP:  		itnim = BFA_ITNIM_FROM_TAG(fcpim,  						msg.create_rsp->bfa_handle); -		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK); +		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);  		bfa_stats(itnim, create_comps);  		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);  		break; -	case BFI_ITNIM_I2H_DELETE_RSP: +	case BFI_ITN_I2H_DELETE_RSP:  		itnim = BFA_ITNIM_FROM_TAG(fcpim,  						msg.delete_rsp->bfa_handle); -		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK); +		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);  		bfa_stats(itnim, delete_comps);  		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);  		break; -	case BFI_ITNIM_I2H_SLER_EVENT: +	case BFI_ITN_I2H_SLER_EVENT:  		itnim = BFA_ITNIM_FROM_TAG(fcpim,  						msg.sler_event->bfa_handle);  		bfa_stats(itnim, sler_events); @@ -1503,24 +1396,24 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  	default:  		bfa_trc(bfa, m->mhdr.msg_id); -		bfa_assert(0); +		WARN_ON(1);  	}  } - -  /* - *  bfa_itnim_api + * bfa_itnim_api   */  struct bfa_itnim_s *  bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct bfa_itnim_s *itnim; +	bfa_itn_create(bfa, rport, bfa_itnim_isr); +  	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag); -	bfa_assert(itnim->rport == rport); +	WARN_ON(itnim->rport != rport);  	itnim->ditn = ditn; @@ -1568,17 +1461,25 @@ bfa_itnim_hold_io(struct bfa_itnim_s *itnim)  		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));  } +#define bfa_io_lat_clock_res_div	HZ +#define bfa_io_lat_clock_res_mul	1000  bfa_status_t  bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, -		struct bfa_itnim_ioprofile_s *ioprofile) +			struct bfa_itnim_ioprofile_s *ioprofile)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa); +	struct bfa_fcpim_s *fcpim; + +	if (!itnim) +		return BFA_STATUS_NO_FCPIM_NEXUS; + +	fcpim = BFA_FCPIM(itnim->bfa); +  	if (!fcpim->io_profile)  		return BFA_STATUS_IOPROFILE_OFF;  	itnim->ioprofile.index = BFA_IOBUCKET_MAX;  	itnim->ioprofile.io_profile_start_time = -		bfa_io_profile_start_time(itnim->bfa); +				bfa_io_profile_start_time(itnim->bfa);  	itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;  	itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;  	*ioprofile = itnim->ioprofile; @@ -1587,16 +1488,13 @@ bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,  }  void -bfa_itnim_get_stats(struct bfa_itnim_s *itnim, -	struct bfa_itnim_iostats_s *stats) -{ -	*stats = itnim->stats; -} - -void  bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)  {  	int j; + +	if (!itnim) +		return; +  	memset(&itnim->stats, 0, sizeof(itnim->stats));  	memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));  	for (j = 0; j < BFA_IOBUCKET_MAX; j++) @@ -1608,14 +1506,11 @@ bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)   */  /* - *	IO is not started (unallocated). + * IO is not started (unallocated).   */  static void  bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  { -	bfa_trc_fp(ioim->bfa, ioim->iotag); -	bfa_trc_fp(ioim->bfa, event); -  	switch (event) {  	case BFA_IOIM_SM_START:  		if (!bfa_itnim_is_online(ioim->itnim)) { @@ -1635,7 +1530,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  		}  		if (ioim->nsges > BFI_SGE_INLINE) { -			if (!bfa_ioim_sge_setup(ioim)) { +			if (!bfa_ioim_sgpg_alloc(ioim)) {  				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);  				return;  			} @@ -1662,9 +1557,9 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  		 * requests immediately.  		 */  		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); -		bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)); +		WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));  		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, -				__bfa_cb_ioim_abort, ioim); +			__bfa_cb_ioim_abort, ioim);  		break;  	default: @@ -1673,7 +1568,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  }  /* - *	IO is waiting for SG pages. + * IO is waiting for SG pages.   */  static void  bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -1720,14 +1615,11 @@ bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  }  /* - *	IO is active. + * IO is active.   */  static void  bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  { -	bfa_trc_fp(ioim->bfa, ioim->iotag); -	bfa_trc_fp(ioim->bfa, event); -  	switch (event) {  	case BFA_IOIM_SM_COMP_GOOD:  		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); @@ -1786,8 +1678,8 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  		break;  	case BFA_IOIM_SM_SQRETRY: -		if (bfa_ioim_get_iotag(ioim) != BFA_TRUE) { -			/* max retry completed free IO */ +		if (bfa_ioim_maxretry_reached(ioim)) { +			/* max retry reached, free IO */  			bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);  			bfa_ioim_move_to_comp_q(ioim);  			bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, @@ -1804,17 +1696,15 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  }  /* -*	IO is retried with new tag. -*/ + * IO is retried with new tag. + */  static void  bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  { -	bfa_trc_fp(ioim->bfa, ioim->iotag); -	bfa_trc_fp(ioim->bfa, event); -  	switch (event) {  	case BFA_IOIM_SM_FREE:  		/* abts and rrq done. Now retry the IO with new tag */ +		bfa_ioim_update_iotag(ioim);  		if (!bfa_ioim_send_ioreq(ioim)) {  			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);  			break; @@ -1858,7 +1748,7 @@ bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  }  /* - *	IO is being aborted, waiting for completion from firmware. + * IO is being aborted, waiting for completion from firmware.   */  static void  bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -1894,7 +1784,7 @@ bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  		break;  	case BFA_IOIM_SM_CLEANUP: -		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE); +		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);  		ioim->iosp->abort_explicit = BFA_FALSE;  		if (bfa_ioim_send_abort(ioim)) @@ -1981,7 +1871,7 @@ bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  }  /* - *	IO is waiting for room in request CQ + * IO is waiting for room in request CQ   */  static void  bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -2025,7 +1915,7 @@ bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  }  /* - *	Active IO is being aborted, waiting for room in request CQ. + * Active IO is being aborted, waiting for room in request CQ.   */  static void  bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -2040,7 +1930,7 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  		break;  	case BFA_IOIM_SM_CLEANUP: -		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE); +		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);  		ioim->iosp->abort_explicit = BFA_FALSE;  		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);  		break; @@ -2076,7 +1966,7 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  }  /* - *	Active IO is being cleaned up, waiting for room in request CQ. + * Active IO is being cleaned up, waiting for room in request CQ.   */  static void  bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -2092,7 +1982,7 @@ bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  	case BFA_IOIM_SM_ABORT:  		/* -		 * IO is alraedy being cleaned up implicitly +		 * IO is already being cleaned up implicitly  		 */  		ioim->io_cbfn = __bfa_cb_ioim_abort;  		break; @@ -2131,9 +2021,6 @@ bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  static void  bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  { -	bfa_trc_fp(ioim->bfa, ioim->iotag); -	bfa_trc_fp(ioim->bfa, event); -  	switch (event) {  	case BFA_IOIM_SM_HCB:  		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit); @@ -2212,11 +2099,27 @@ bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)  	}  } - -  /* - *  hal_ioim_private + * This is called from bfa_fcpim_start after the bfa_init() with flash read + * is complete by driver. now invalidate the stale content of lun mask + * like unit attention, rp tag and lp tag.   */ +static void +bfa_ioim_lm_init(struct bfa_s *bfa) +{ +	struct bfa_lun_mask_s *lunm_list; +	int	i; + +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) +		return; + +	lunm_list = bfa_get_lun_mask_list(bfa); +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		lunm_list[i].ua = BFA_IOIM_LM_UA_RESET; +		lunm_list[i].lp_tag = BFA_LP_TAG_INVALID; +		lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID; +	} +}  static void  __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete) @@ -2253,7 +2156,8 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)  		if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&  					m->sns_len) {  			sns_len = m->sns_len; -			snsinfo = ioim->iosp->snsinfo; +			snsinfo = BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp, +						ioim->iotag);  		}  		/* @@ -2274,6 +2178,224 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)  			  m->scsi_status, sns_len, snsinfo, residue);  } +void +bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn, +			u16 rp_tag, u8 lp_tag) +{ +	struct bfa_lun_mask_s *lun_list; +	u8	i; + +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) +		return; + +	lun_list = bfa_get_lun_mask_list(bfa); +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) { +			if ((lun_list[i].lp_wwn == lp_wwn) && +			    (lun_list[i].rp_wwn == rp_wwn)) { +				lun_list[i].rp_tag = rp_tag; +				lun_list[i].lp_tag = lp_tag; +			} +		} +	} +} + +/* + * set UA for all active luns in LM DB + */ +static void +bfa_ioim_lm_set_ua(struct bfa_s *bfa) +{ +	struct bfa_lun_mask_s	*lunm_list; +	int	i; + +	lunm_list = bfa_get_lun_mask_list(bfa); +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) +			continue; +		lunm_list[i].ua = BFA_IOIM_LM_UA_SET; +	} +} + +bfa_status_t +bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 update) +{ +	struct bfa_lunmask_cfg_s	*lun_mask; + +	bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) +		return BFA_STATUS_FAILED; + +	if (bfa_get_lun_mask_status(bfa) == update) +		return BFA_STATUS_NO_CHANGE; + +	lun_mask = bfa_get_lun_mask(bfa); +	lun_mask->status = update; + +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) +		bfa_ioim_lm_set_ua(bfa); + +	return  bfa_dconf_update(bfa); +} + +bfa_status_t +bfa_fcpim_lunmask_clear(struct bfa_s *bfa) +{ +	int i; +	struct bfa_lun_mask_s	*lunm_list; + +	bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) +		return BFA_STATUS_FAILED; + +	lunm_list = bfa_get_lun_mask_list(bfa); +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if (lunm_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE) { +			if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID) +				bfa_rport_unset_lunmask(bfa, +				  BFA_RPORT_FROM_TAG(bfa, lunm_list[i].rp_tag)); +		} +	} + +	memset(lunm_list, 0, sizeof(struct bfa_lun_mask_s) * MAX_LUN_MASK_CFG); +	return bfa_dconf_update(bfa); +} + +bfa_status_t +bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf) +{ +	struct bfa_lunmask_cfg_s *lun_mask; + +	bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) +		return BFA_STATUS_FAILED; + +	lun_mask = bfa_get_lun_mask(bfa); +	memcpy(buf, lun_mask, sizeof(struct bfa_lunmask_cfg_s)); +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, +		      wwn_t rpwwn, struct scsi_lun lun) +{ +	struct bfa_lun_mask_s *lunm_list; +	struct bfa_rport_s *rp = NULL; +	int i, free_index = MAX_LUN_MASK_CFG + 1; +	struct bfa_fcs_lport_s *port = NULL; +	struct bfa_fcs_rport_s *rp_fcs; + +	bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) +		return BFA_STATUS_FAILED; + +	port = bfa_fcs_lookup_port(&((struct bfad_s *)bfa->bfad)->bfa_fcs, +				   vf_id, *pwwn); +	if (port) { +		*pwwn = port->port_cfg.pwwn; +		rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn); +		if (rp_fcs) +			rp = rp_fcs->bfa_rport; +	} + +	lunm_list = bfa_get_lun_mask_list(bfa); +	/* if entry exists */ +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if (lunm_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) +			free_index = i; +		if ((lunm_list[i].lp_wwn == *pwwn) && +		    (lunm_list[i].rp_wwn == rpwwn) && +		    (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) == +		     scsilun_to_int((struct scsi_lun *)&lun))) +			return  BFA_STATUS_ENTRY_EXISTS; +	} + +	if (free_index > MAX_LUN_MASK_CFG) +		return BFA_STATUS_MAX_ENTRY_REACHED; + +	if (rp) { +		lunm_list[free_index].lp_tag = bfa_lps_get_tag_from_pid(bfa, +						   rp->rport_info.local_pid); +		lunm_list[free_index].rp_tag = rp->rport_tag; +	} else { +		lunm_list[free_index].lp_tag = BFA_LP_TAG_INVALID; +		lunm_list[free_index].rp_tag = BFA_RPORT_TAG_INVALID; +	} + +	lunm_list[free_index].lp_wwn = *pwwn; +	lunm_list[free_index].rp_wwn = rpwwn; +	lunm_list[free_index].lun = lun; +	lunm_list[free_index].state = BFA_IOIM_LUN_MASK_ACTIVE; + +	/* set for all luns in this rp */ +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if ((lunm_list[i].lp_wwn == *pwwn) && +		    (lunm_list[i].rp_wwn == rpwwn)) +			lunm_list[i].ua = BFA_IOIM_LM_UA_SET; +	} + +	return bfa_dconf_update(bfa); +} + +bfa_status_t +bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, +			 wwn_t rpwwn, struct scsi_lun lun) +{ +	struct bfa_lun_mask_s	*lunm_list; +	struct bfa_rport_s	*rp = NULL; +	struct bfa_fcs_lport_s *port = NULL; +	struct bfa_fcs_rport_s *rp_fcs; +	int	i; + +	/* in min cfg lunm_list could be NULL but  no commands should run. */ +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_MINCFG) +		return BFA_STATUS_FAILED; + +	bfa_trc(bfa, bfa_get_lun_mask_status(bfa)); +	bfa_trc(bfa, *pwwn); +	bfa_trc(bfa, rpwwn); +	bfa_trc(bfa, scsilun_to_int((struct scsi_lun *)&lun)); + +	if (*pwwn == 0) { +		port = bfa_fcs_lookup_port( +				&((struct bfad_s *)bfa->bfad)->bfa_fcs, +				vf_id, *pwwn); +		if (port) { +			*pwwn = port->port_cfg.pwwn; +			rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn); +			if (rp_fcs) +				rp = rp_fcs->bfa_rport; +		} +	} + +	lunm_list = bfa_get_lun_mask_list(bfa); +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if ((lunm_list[i].lp_wwn == *pwwn) && +		    (lunm_list[i].rp_wwn == rpwwn) && +		    (scsilun_to_int((struct scsi_lun *)&lunm_list[i].lun) == +		     scsilun_to_int((struct scsi_lun *)&lun))) { +			lunm_list[i].lp_wwn = 0; +			lunm_list[i].rp_wwn = 0; +			int_to_scsilun(0, &lunm_list[i].lun); +			lunm_list[i].state = BFA_IOIM_LUN_MASK_INACTIVE; +			if (lunm_list[i].rp_tag != BFA_RPORT_TAG_INVALID) { +				lunm_list[i].rp_tag = BFA_RPORT_TAG_INVALID; +				lunm_list[i].lp_tag = BFA_LP_TAG_INVALID; +			} +			return bfa_dconf_update(bfa); +		} +	} + +	/* set for all luns in this rp */ +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if ((lunm_list[i].lp_wwn == *pwwn) && +		    (lunm_list[i].rp_wwn == rpwwn)) +			lunm_list[i].ua = BFA_IOIM_LM_UA_SET; +	} + +	return BFA_STATUS_ENTRY_NOT_EXISTS; +} +  static void  __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)  { @@ -2323,7 +2445,7 @@ bfa_ioim_sgpg_alloced(void *cbarg)  	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);  	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q); -	bfa_ioim_sgpg_setup(ioim); +	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);  	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);  } @@ -2335,13 +2457,16 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)  {  	struct bfa_itnim_s *itnim = ioim->itnim;  	struct bfi_ioim_req_s *m; -	static struct fcp_cmnd_s cmnd_z0 = { 0 }; -	struct bfi_sge_s      *sge; +	static struct fcp_cmnd_s cmnd_z0 = { { { 0 } } }; +	struct bfi_sge_s *sge, *sgpge;  	u32	pgdlen = 0;  	u32	fcp_dl;  	u64 addr;  	struct scatterlist *sg; +	struct bfa_sgpg_s *sgpg;  	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; +	u32 i, sge_id, pgcumsz; +	enum dma_data_direction dmadir;  	/*  	 * check for room in queue to send request now @@ -2359,22 +2484,61 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)  	 */  	m->io_tag = cpu_to_be16(ioim->iotag);  	m->rport_hdl = ioim->itnim->rport->fw_handle; -	m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio); +	m->io_timeout = 0; -	/* -	 * build inline IO SG element here -	 */  	sge = &m->sges[0]; -	if (ioim->nsges) { -		sg = (struct scatterlist *)scsi_sglist(cmnd); -		addr = bfa_os_sgaddr(sg_dma_address(sg)); -		sge->sga = *(union bfi_addr_u *) &addr; -		pgdlen = sg_dma_len(sg); -		sge->sg_len = pgdlen; -		sge->flags = (ioim->nsges > BFI_SGE_INLINE) ? +	sgpg = ioim->sgpg; +	sge_id = 0; +	sgpge = NULL; +	pgcumsz = 0; +	scsi_for_each_sg(cmnd, sg, ioim->nsges, i) { +		if (i == 0) { +			/* build inline IO SG element */ +			addr = bfa_sgaddr_le(sg_dma_address(sg)); +			sge->sga = *(union bfi_addr_u *) &addr; +			pgdlen = sg_dma_len(sg); +			sge->sg_len = pgdlen; +			sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?  					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST; -		bfa_sge_to_be(sge); -		sge++; +			bfa_sge_to_be(sge); +			sge++; +		} else { +			if (sge_id == 0) +				sgpge = sgpg->sgpg->sges; + +			addr = bfa_sgaddr_le(sg_dma_address(sg)); +			sgpge->sga = *(union bfi_addr_u *) &addr; +			sgpge->sg_len = sg_dma_len(sg); +			pgcumsz += sgpge->sg_len; + +			/* set flags */ +			if (i < (ioim->nsges - 1) && +					sge_id < (BFI_SGPG_DATA_SGES - 1)) +				sgpge->flags = BFI_SGE_DATA; +			else if (i < (ioim->nsges - 1)) +				sgpge->flags = BFI_SGE_DATA_CPL; +			else +				sgpge->flags = BFI_SGE_DATA_LAST; + +			bfa_sge_to_le(sgpge); + +			sgpge++; +			if (i == (ioim->nsges - 1)) { +				sgpge->flags = BFI_SGE_PGDLEN; +				sgpge->sga.a32.addr_lo = 0; +				sgpge->sga.a32.addr_hi = 0; +				sgpge->sg_len = pgcumsz; +				bfa_sge_to_le(sgpge); +			} else if (++sge_id == BFI_SGPG_DATA_SGES) { +				sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg); +				sgpge->flags = BFI_SGE_LINK; +				sgpge->sga = sgpg->sgpg_pa; +				sgpge->sg_len = pgcumsz; +				bfa_sge_to_le(sgpge); +				sge_id = 0; +				pgcumsz = 0; +			} +		}  	}  	if (ioim->nsges > BFI_SGE_INLINE) { @@ -2391,10 +2555,17 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)  	 * set up I/O command parameters  	 */  	m->cmnd = cmnd_z0; -	m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio); -	m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio); -	m->cmnd.cdb = *(scsi_cdb_t *)bfa_cb_ioim_get_cdb(ioim->dio); -	fcp_dl = bfa_cb_ioim_get_size(ioim->dio); +	int_to_scsilun(cmnd->device->lun, &m->cmnd.lun); +	dmadir = cmnd->sc_data_direction; +	if (dmadir == DMA_TO_DEVICE) +		m->cmnd.iodir = FCP_IODIR_WRITE; +	else if (dmadir == DMA_FROM_DEVICE) +		m->cmnd.iodir = FCP_IODIR_READ; +	else +		m->cmnd.iodir = FCP_IODIR_NONE; + +	m->cmnd.cdb = *(struct scsi_cdb_s *) cmnd->cmnd; +	fcp_dl = scsi_bufflen(cmnd);  	m->cmnd.fcp_dl = cpu_to_be32(fcp_dl);  	/* @@ -2402,12 +2573,12 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)  	 */  	switch (m->cmnd.iodir) {  	case FCP_IODIR_READ: -		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa)); +		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_fn_lpu(ioim->bfa));  		bfa_stats(itnim, input_reqs);  		ioim->itnim->stats.rd_throughput += fcp_dl;  		break;  	case FCP_IODIR_WRITE: -		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa)); +		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_fn_lpu(ioim->bfa));  		bfa_stats(itnim, output_reqs);  		ioim->itnim->stats.wr_throughput += fcp_dl;  		break; @@ -2415,35 +2586,16 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)  		bfa_stats(itnim, input_reqs);  		bfa_stats(itnim, output_reqs);  	default: -		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa)); +		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));  	}  	if (itnim->seq_rec || -	    (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1))) -		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa)); - -#ifdef IOIM_ADVANCED -	m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio); -	m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio); -	m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio); - -	/* -	 * Handle large CDB (>16 bytes). -	 */ -	m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) - -					FCP_CMND_CDB_LEN) / sizeof(u32); -	if (m->cmnd.addl_cdb_len) { -		memcpy(&m->cmnd.cdb + 1, (scsi_cdb_t *) -				bfa_cb_ioim_get_cdb(ioim->dio) + 1, -				m->cmnd.addl_cdb_len * sizeof(u32)); -		fcp_cmnd_fcpdl(&m->cmnd) = -				cpu_to_be32(bfa_cb_ioim_get_size(ioim->dio)); -	} -#endif +	    (scsi_bufflen(cmnd) & (sizeof(u32) - 1))) +		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(ioim->bfa, ioim->reqq); +	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);  	return BFA_TRUE;  } @@ -2452,11 +2604,11 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)   * at queuing time.   */  static bfa_boolean_t -bfa_ioim_sge_setup(struct bfa_ioim_s *ioim) +bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim)  {  	u16	nsgpgs; -	bfa_assert(ioim->nsges > BFI_SGE_INLINE); +	WARN_ON(ioim->nsges <= BFI_SGE_INLINE);  	/*  	 * allocate SG pages needed @@ -2472,73 +2624,11 @@ bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)  	}  	ioim->nsgpgs = nsgpgs; -	bfa_ioim_sgpg_setup(ioim); +	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);  	return BFA_TRUE;  } -static void -bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim) -{ -	int		sgeid, nsges, i; -	struct bfi_sge_s      *sge; -	struct bfa_sgpg_s *sgpg; -	u32	pgcumsz; -	u64        addr; -	struct scatterlist *sg; -	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; - -	sgeid = BFI_SGE_INLINE; -	ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q); - -	sg = scsi_sglist(cmnd); -	sg = sg_next(sg); - -	do { -		sge = sgpg->sgpg->sges; -		nsges = ioim->nsges - sgeid; -		if (nsges > BFI_SGPG_DATA_SGES) -			nsges = BFI_SGPG_DATA_SGES; - -		pgcumsz = 0; -		for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) { -			addr = bfa_os_sgaddr(sg_dma_address(sg)); -			sge->sga = *(union bfi_addr_u *) &addr; -			sge->sg_len = sg_dma_len(sg); -			pgcumsz += sge->sg_len; - -			/* -			 * set flags -			 */ -			if (i < (nsges - 1)) -				sge->flags = BFI_SGE_DATA; -			else if (sgeid < (ioim->nsges - 1)) -				sge->flags = BFI_SGE_DATA_CPL; -			else -				sge->flags = BFI_SGE_DATA_LAST; - -			bfa_sge_to_le(sge); -		} - -		sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg); - -		/* -		 * set the link element of each page -		 */ -		if (sgeid == ioim->nsges) { -			sge->flags = BFI_SGE_PGDLEN; -			sge->sga.a32.addr_lo = 0; -			sge->sga.a32.addr_hi = 0; -		} else { -			sge->flags = BFI_SGE_LINK; -			sge->sga = sgpg->sgpg_pa; -		} -		sge->sg_len = pgcumsz; - -		bfa_sge_to_le(sge); -	} while (sgeid < ioim->nsges); -} -  /*   * Send I/O abort request to firmware.   */ @@ -2563,14 +2653,14 @@ bfa_ioim_send_abort(struct bfa_ioim_s *ioim)  	else  		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ; -	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa)); +	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_fn_lpu(ioim->bfa));  	m->io_tag    = cpu_to_be16(ioim->iotag);  	m->abort_tag = ++ioim->abort_tag;  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(ioim->bfa, ioim->reqq); +	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);  	return BFA_TRUE;  } @@ -2605,7 +2695,7 @@ bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)  		}  		bfa_itnim_iodone(ioim->itnim);  	} else -		bfa_tskim_iodone(ioim->iosp->tskim); +		bfa_wc_down(&ioim->iosp->tskim->wc);  }  static bfa_boolean_t @@ -2623,9 +2713,6 @@ bfa_ioim_is_abortable(struct bfa_ioim_s *ioim)  	return BFA_TRUE;  } -/* - *	or after the link comes back. - */  void  bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)  { @@ -2653,55 +2740,36 @@ bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)  } - -/* - *  hal_ioim_friend - */ -  /*   * Memory allocation and initialization.   */  void -bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) +bfa_ioim_attach(struct bfa_fcpim_s *fcpim)  {  	struct bfa_ioim_s		*ioim; +	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;  	struct bfa_ioim_sp_s	*iosp;  	u16		i; -	u8			*snsinfo; -	u32		snsbufsz;  	/*  	 * claim memory first  	 */ -	ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo); +	ioim = (struct bfa_ioim_s *) bfa_mem_kva_curp(fcp);  	fcpim->ioim_arr = ioim; -	bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs); +	bfa_mem_kva_curp(fcp) = (u8 *) (ioim + fcpim->fcp->num_ioim_reqs); -	iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo); +	iosp = (struct bfa_ioim_sp_s *) bfa_mem_kva_curp(fcp);  	fcpim->ioim_sp_arr = iosp; -	bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs); - -	/* -	 * Claim DMA memory for per IO sense data. -	 */ -	snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN; -	fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo); -	bfa_meminfo_dma_phys(minfo) += snsbufsz; - -	fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo); -	bfa_meminfo_dma_virt(minfo) += snsbufsz; -	snsinfo = fcpim->snsbase.kva; -	bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa); +	bfa_mem_kva_curp(fcp) = (u8 *) (iosp + fcpim->fcp->num_ioim_reqs);  	/*  	 * Initialize ioim free queues  	 */ -	INIT_LIST_HEAD(&fcpim->ioim_free_q);  	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);  	INIT_LIST_HEAD(&fcpim->ioim_comp_q); -	for (i = 0; i < fcpim->num_ioim_reqs; -	     i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) { +	for (i = 0; i < fcpim->fcp->num_ioim_reqs; +	     i++, ioim++, iosp++) {  		/*  		 * initialize IOIM  		 */ @@ -2710,30 +2778,19 @@ bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)  		ioim->bfa     = fcpim->bfa;  		ioim->fcpim   = fcpim;  		ioim->iosp    = iosp; -		iosp->snsinfo = snsinfo;  		INIT_LIST_HEAD(&ioim->sgpg_q);  		bfa_reqq_winit(&ioim->iosp->reqq_wait,  				   bfa_ioim_qresume, ioim);  		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,  				   bfa_ioim_sgpg_alloced, ioim);  		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit); - -		list_add_tail(&ioim->qe, &fcpim->ioim_free_q);  	}  } -/* - * Driver detach time call. - */ -void -bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim) -{ -} -  void  bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;  	struct bfa_ioim_s *ioim;  	u16	iotag; @@ -2742,7 +2799,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  	iotag = be16_to_cpu(rsp->io_tag);  	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); -	bfa_assert(ioim->iotag == iotag); +	WARN_ON(ioim->iotag != iotag);  	bfa_trc(ioim->bfa, ioim->iotag);  	bfa_trc(ioim->bfa, rsp->io_status); @@ -2773,13 +2830,13 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  	case BFI_IOIM_STS_PROTO_ERR:  		bfa_stats(ioim->itnim, iocom_proto_err); -		bfa_assert(rsp->reuse_io_tag); +		WARN_ON(!rsp->reuse_io_tag);  		evt = BFA_IOIM_SM_COMP;  		break;  	case BFI_IOIM_STS_SQER_NEEDED:  		bfa_stats(ioim->itnim, iocom_sqer_needed); -		bfa_assert(rsp->reuse_io_tag == 0); +		WARN_ON(rsp->reuse_io_tag != 0);  		evt = BFA_IOIM_SM_SQRETRY;  		break; @@ -2808,7 +2865,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  	}  	bfa_sm_send_event(ioim, evt); @@ -2817,7 +2874,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  void  bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;  	struct bfa_ioim_s *ioim;  	u16	iotag; @@ -2825,39 +2882,13 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  	iotag = be16_to_cpu(rsp->io_tag);  	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); -	bfa_assert(ioim->iotag == iotag); +	WARN_ON(ioim->iotag != iotag); -	bfa_trc_fp(ioim->bfa, ioim->iotag);  	bfa_ioim_cb_profile_comp(fcpim, ioim);  	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);  } -void -bfa_ioim_profile_start(struct bfa_ioim_s *ioim) -{ -	ioim->start_time = jiffies; -} - -void -bfa_ioim_profile_comp(struct bfa_ioim_s *ioim) -{ -	u32 fcp_dl = bfa_cb_ioim_get_size(ioim->dio); -	u32 index = bfa_ioim_get_index(fcp_dl); -	u64 end_time = jiffies; -	struct bfa_itnim_latency_s *io_lat = -			&(ioim->itnim->ioprofile.io_latency); -	u32 val = (u32)(end_time - ioim->start_time); - -	bfa_itnim_ioprofile_update(ioim->itnim, index); - -	io_lat->count[index]++; -	io_lat->min[index] = (io_lat->min[index] < val) ? -		io_lat->min[index] : val; -	io_lat->max[index] = (io_lat->max[index] > val) ? -		io_lat->max[index] : val; -	io_lat->avg[index] += val; -}  /*   * Called by itnim to clean up IO while going offline.   */ @@ -2903,11 +2934,6 @@ bfa_ioim_tov(struct bfa_ioim_s *ioim)  } - -/* - *  hal_ioim_api - */ -  /*   * Allocate IOIM resource for initiator mode I/O request.   */ @@ -2915,18 +2941,21 @@ struct bfa_ioim_s *  bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,  		struct bfa_itnim_s *itnim, u16 nsges)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct bfa_ioim_s *ioim; +	struct bfa_iotag_s *iotag = NULL;  	/*  	 * alocate IOIM resource  	 */ -	bfa_q_deq(&fcpim->ioim_free_q, &ioim); -	if (!ioim) { +	bfa_q_deq(&fcpim->fcp->iotag_ioim_free_q, &iotag); +	if (!iotag) {  		bfa_stats(itnim, no_iotags);  		return NULL;  	} +	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag->tag); +  	ioim->dio = dio;  	ioim->itnim = itnim;  	ioim->nsges = nsges; @@ -2936,7 +2965,6 @@ bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,  	fcpim->ios_active++;  	list_add_tail(&ioim->qe, &itnim->io_q); -	bfa_trc_fp(ioim->bfa, ioim->iotag);  	return ioim;  } @@ -2944,13 +2972,8 @@ bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,  void  bfa_ioim_free(struct bfa_ioim_s *ioim)  { -	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim; - -	bfa_trc_fp(ioim->bfa, ioim->iotag); -	bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit)); - -	bfa_assert_fp(list_empty(&ioim->sgpg_q) || -			(ioim->nsges > BFI_SGE_INLINE)); +	struct bfa_fcpim_s *fcpim = ioim->fcpim; +	struct bfa_iotag_s *iotag;  	if (ioim->nsgpgs > 0)  		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs); @@ -2958,23 +2981,30 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)  	bfa_stats(ioim->itnim, io_comps);  	fcpim->ios_active--; +	ioim->iotag &= BFA_IOIM_IOTAG_MASK; + +	WARN_ON(!(ioim->iotag < +		(fcpim->fcp->num_ioim_reqs + fcpim->fcp->num_fwtio_reqs))); +	iotag = BFA_IOTAG_FROM_TAG(fcpim->fcp, ioim->iotag); + +	if (ioim->iotag < fcpim->fcp->num_ioim_reqs) +		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_ioim_free_q); +	else +		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_tio_free_q); +  	list_del(&ioim->qe); -	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);  }  void  bfa_ioim_start(struct bfa_ioim_s *ioim)  { -	bfa_trc_fp(ioim->bfa, ioim->iotag); -  	bfa_ioim_cb_profile_start(ioim->fcpim, ioim);  	/*  	 * Obtain the queue over which this request has to be issued  	 */  	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ? -			bfa_cb_ioim_get_reqq(ioim->dio) : -			bfa_itnim_get_reqq(ioim); +			BFA_FALSE : bfa_itnim_get_reqq(ioim);  	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);  } @@ -2997,18 +3027,17 @@ bfa_ioim_abort(struct bfa_ioim_s *ioim)  	return BFA_STATUS_OK;  } -  /*   *  BFA TSKIM state machine functions   */  /* - *	Task management command beginning state. + * Task management command beginning state.   */  static void  bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  { -	bfa_trc(tskim->bfa, event); +	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);  	switch (event) {  	case BFA_TSKIM_SM_START: @@ -3040,14 +3069,13 @@ bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  }  /* - * brief - *	TM command is active, awaiting completion from firmware to - *	cleanup IO requests in TM scope. + * TM command is active, awaiting completion from firmware to + * cleanup IO requests in TM scope.   */  static void  bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  { -	bfa_trc(tskim->bfa, event); +	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);  	switch (event) {  	case BFA_TSKIM_SM_DONE: @@ -3077,13 +3105,13 @@ bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  }  /* - *	An active TM is being cleaned up since ITN is offline. Awaiting cleanup - *	completion event from firmware. + * An active TM is being cleaned up since ITN is offline. Awaiting cleanup + * completion event from firmware.   */  static void  bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  { -	bfa_trc(tskim->bfa, event); +	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);  	switch (event) {  	case BFA_TSKIM_SM_DONE: @@ -3092,6 +3120,7 @@ bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  		 */  		break; +	case BFA_TSKIM_SM_UTAG:  	case BFA_TSKIM_SM_CLEANUP_DONE:  		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);  		bfa_tskim_cleanup_ios(tskim); @@ -3111,7 +3140,7 @@ bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  static void  bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  { -	bfa_trc(tskim->bfa, event); +	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);  	switch (event) {  	case BFA_TSKIM_SM_IOS_DONE: @@ -3138,12 +3167,12 @@ bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  }  /* - *	Task management command is waiting for room in request CQ + * Task management command is waiting for room in request CQ   */  static void  bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  { -	bfa_trc(tskim->bfa, event); +	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);  	switch (event) {  	case BFA_TSKIM_SM_QRESUME: @@ -3173,23 +3202,21 @@ bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  }  /* - *	Task management command is active, awaiting for room in request CQ - *	to send clean up request. + * Task management command is active, awaiting for room in request CQ + * to send clean up request.   */  static void  bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,  		enum bfa_tskim_event event)  { -	bfa_trc(tskim->bfa, event); +	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);  	switch (event) {  	case BFA_TSKIM_SM_DONE:  		bfa_reqq_wcancel(&tskim->reqq_wait);  		/* -		 *  		 * Fall through !!!  		 */ -  	case BFA_TSKIM_SM_QRESUME:  		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);  		bfa_tskim_send_abort(tskim); @@ -3208,12 +3235,12 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,  }  /* - *	BFA callback is pending + * BFA callback is pending   */  static void  bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  { -	bfa_trc(tskim->bfa, event); +	bfa_trc(tskim->bfa, tskim->tsk_tag << 16 | event);  	switch (event) {  	case BFA_TSKIM_SM_HCB: @@ -3233,12 +3260,6 @@ bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)  	}  } - - -/* - *  hal_tskim_private - */ -  static void  __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)  { @@ -3268,8 +3289,8 @@ __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)  				BFI_TSKIM_STS_FAILED);  } -static	bfa_boolean_t -bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun) +static bfa_boolean_t +bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun)  {  	switch (tskim->tm_cmnd) {  	case FCP_TM_TARGET_RESET: @@ -3279,24 +3300,26 @@ bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)  	case FCP_TM_CLEAR_TASK_SET:  	case FCP_TM_LUN_RESET:  	case FCP_TM_CLEAR_ACA: -		return (tskim->lun == lun); +		return !memcmp(&tskim->lun, &lun, sizeof(lun));  	default: -		bfa_assert(0); +		WARN_ON(1);  	}  	return BFA_FALSE;  }  /* - *	Gather affected IO requests and task management commands. + * Gather affected IO requests and task management commands.   */  static void  bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)  {  	struct bfa_itnim_s *itnim = tskim->itnim;  	struct bfa_ioim_s *ioim; -	struct list_head	*qe, *qen; +	struct list_head *qe, *qen; +	struct scsi_cmnd *cmnd; +	struct scsi_lun scsilun;  	INIT_LIST_HEAD(&tskim->io_q); @@ -3305,8 +3328,9 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)  	 */  	list_for_each_safe(qe, qen, &itnim->io_q) {  		ioim = (struct bfa_ioim_s *) qe; -		if (bfa_tskim_match_scope -			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) { +		cmnd = (struct scsi_cmnd *) ioim->dio; +		int_to_scsilun(cmnd->device->lun, &scsilun); +		if (bfa_tskim_match_scope(tskim, scsilun)) {  			list_del(&ioim->qe);  			list_add_tail(&ioim->qe, &tskim->io_q);  		} @@ -3317,8 +3341,9 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)  	 */  	list_for_each_safe(qe, qen, &itnim->pending_q) {  		ioim = (struct bfa_ioim_s *) qe; -		if (bfa_tskim_match_scope -			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) { +		cmnd = (struct scsi_cmnd *) ioim->dio; +		int_to_scsilun(cmnd->device->lun, &scsilun); +		if (bfa_tskim_match_scope(tskim, scsilun)) {  			list_del(&ioim->qe);  			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);  			bfa_ioim_tov(ioim); @@ -3327,7 +3352,7 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)  }  /* - *	IO cleanup completion + * IO cleanup completion   */  static void  bfa_tskim_cleanp_comp(void *tskim_cbarg) @@ -3339,7 +3364,7 @@ bfa_tskim_cleanp_comp(void *tskim_cbarg)  }  /* - *	Gather affected IO requests and task management commands. + * Gather affected IO requests and task management commands.   */  static void  bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim) @@ -3359,7 +3384,7 @@ bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)  }  /* - *	Send task management request to firmware. + * Send task management request to firmware.   */  static bfa_boolean_t  bfa_tskim_send(struct bfa_tskim_s *tskim) @@ -3378,7 +3403,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)  	 * build i/o request message next  	 */  	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ, -			bfa_lpuid(tskim->bfa)); +			bfa_fn_lpu(tskim->bfa));  	m->tsk_tag = cpu_to_be16(tskim->tsk_tag);  	m->itn_fhdl = tskim->itnim->rport->fw_handle; @@ -3389,12 +3414,12 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(tskim->bfa, itnim->reqq); +	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);  	return BFA_TRUE;  }  /* - *	Send abort request to cleanup an active TM to firmware. + * Send abort request to cleanup an active TM to firmware.   */  static bfa_boolean_t  bfa_tskim_send_abort(struct bfa_tskim_s *tskim) @@ -3413,19 +3438,19 @@ bfa_tskim_send_abort(struct bfa_tskim_s *tskim)  	 * build i/o request message next  	 */  	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ, -			bfa_lpuid(tskim->bfa)); +			bfa_fn_lpu(tskim->bfa));  	m->tsk_tag  = cpu_to_be16(tskim->tsk_tag);  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(tskim->bfa, itnim->reqq); +	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);  	return BFA_TRUE;  }  /* - *	Call to resume task management cmnd waiting for room in request queue. + * Call to resume task management cmnd waiting for room in request queue.   */  static void  bfa_tskim_qresume(void *cbarg) @@ -3451,12 +3476,6 @@ bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)  	}  } - - -/* - *  hal_tskim_friend - */ -  /*   * Notification on completions from related ioim.   */ @@ -3489,17 +3508,19 @@ bfa_tskim_cleanup(struct bfa_tskim_s *tskim)  }  /* - *	Memory allocation and initialization. + * Memory allocation and initialization.   */  void -bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) +bfa_tskim_attach(struct bfa_fcpim_s *fcpim)  {  	struct bfa_tskim_s *tskim; +	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;  	u16	i;  	INIT_LIST_HEAD(&fcpim->tskim_free_q); +	INIT_LIST_HEAD(&fcpim->tskim_unused_q); -	tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo); +	tskim = (struct bfa_tskim_s *) bfa_mem_kva_curp(fcp);  	fcpim->tskim_arr = tskim;  	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) { @@ -3518,27 +3539,19 @@ bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)  		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);  	} -	bfa_meminfo_kva(minfo) = (u8 *) tskim; -} - -void -bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim) -{ -	/* -	* @todo -	*/ +	bfa_mem_kva_curp(fcp) = (u8 *) tskim;  }  void  bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;  	struct bfa_tskim_s *tskim;  	u16	tsk_tag = be16_to_cpu(rsp->tsk_tag);  	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag); -	bfa_assert(tskim->tsk_tag == tsk_tag); +	WARN_ON(tskim->tsk_tag != tsk_tag);  	tskim->tsk_status = rsp->tsk_status; @@ -3549,6 +3562,8 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  	if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {  		bfa_stats(tskim->itnim, tm_cleanup_comps);  		bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE); +	} else if (rsp->tsk_status == BFI_TSKIM_STS_UTAG) { +		bfa_sm_send_event(tskim, BFA_TSKIM_SM_UTAG);  	} else {  		bfa_stats(tskim->itnim, tm_fw_rsps);  		bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE); @@ -3556,16 +3571,10 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  } - -/* - *  hal_tskim_api - */ - -  struct bfa_tskim_s *  bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)  { -	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);  	struct bfa_tskim_s *tskim;  	bfa_q_deq(&fcpim->tskim_free_q, &tskim); @@ -3579,13 +3588,13 @@ bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)  void  bfa_tskim_free(struct bfa_tskim_s *tskim)  { -	bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe)); +	WARN_ON(!bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));  	list_del(&tskim->qe);  	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);  }  /* - *	Start a task management command. + * Start a task management command.   *   * @param[in]	tskim	BFA task management command instance   * @param[in]	itnim	i-t nexus for the task management command @@ -3596,7 +3605,8 @@ bfa_tskim_free(struct bfa_tskim_s *tskim)   * @return None.   */  void -bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun, +bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, +			struct scsi_lun lun,  			enum fcp_tm_cmnd tm_cmnd, u8 tsecs)  {  	tskim->itnim	= itnim; @@ -3609,3 +3619,318 @@ bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,  	list_add_tail(&tskim->qe, &itnim->tsk_q);  	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);  } + +void +bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw) +{ +	struct bfa_fcpim_s	*fcpim = BFA_FCPIM(bfa); +	struct list_head	*qe; +	int	i; + +	for (i = 0; i < (fcpim->num_tskim_reqs - num_tskim_fw); i++) { +		bfa_q_deq_tail(&fcpim->tskim_free_q, &qe); +		list_add_tail(qe, &fcpim->tskim_unused_q); +	} +} + +/* BFA FCP module - parent module for fcpim */ + +BFA_MODULE(fcp); + +static void +bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo, +		struct bfa_s *bfa) +{ +	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); +	struct bfa_mem_kva_s *fcp_kva = BFA_MEM_FCP_KVA(bfa); +	struct bfa_mem_dma_s *seg_ptr; +	u16	nsegs, idx, per_seg_ios, num_io_req; +	u32	km_len = 0; + +	/* +	 * ZERO for num_ioim_reqs and num_fwtio_reqs is allowed config value. +	 * So if the values are non zero, adjust them appropriately. +	 */ +	if (cfg->fwcfg.num_ioim_reqs && +	    cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN) +		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN; +	else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX) +		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX; + +	if (cfg->fwcfg.num_fwtio_reqs > BFA_FWTIO_MAX) +		cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX; + +	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs); +	if (num_io_req > BFA_IO_MAX) { +		if (cfg->fwcfg.num_ioim_reqs && cfg->fwcfg.num_fwtio_reqs) { +			cfg->fwcfg.num_ioim_reqs = BFA_IO_MAX/2; +			cfg->fwcfg.num_fwtio_reqs = BFA_IO_MAX/2; +		} else if (cfg->fwcfg.num_fwtio_reqs) +			cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX; +		else +			cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX; +	} + +	bfa_fcpim_meminfo(cfg, &km_len); + +	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs); +	km_len += num_io_req * sizeof(struct bfa_iotag_s); +	km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itn_s); + +	/* dma memory */ +	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN); +	per_seg_ios = BFI_MEM_NREQS_SEG(BFI_IOIM_SNSLEN); + +	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) { +		if (num_io_req >= per_seg_ios) { +			num_io_req -= per_seg_ios; +			bfa_mem_dma_setup(minfo, seg_ptr, +				per_seg_ios * BFI_IOIM_SNSLEN); +		} else +			bfa_mem_dma_setup(minfo, seg_ptr, +				num_io_req * BFI_IOIM_SNSLEN); +	} + +	/* kva memory */ +	bfa_mem_kva_setup(minfo, fcp_kva, km_len); +} + +static void +bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, +		struct bfa_pcidev_s *pcidev) +{ +	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); +	struct bfa_mem_dma_s *seg_ptr; +	u16	idx, nsegs, num_io_req; + +	fcp->max_ioim_reqs = cfg->fwcfg.num_ioim_reqs; +	fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs; +	fcp->num_fwtio_reqs  = cfg->fwcfg.num_fwtio_reqs; +	fcp->num_itns   = cfg->fwcfg.num_rports; +	fcp->bfa = bfa; + +	/* +	 * Setup the pool of snsbase addr's, that is passed to fw as +	 * part of bfi_iocfc_cfg_s. +	 */ +	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs); +	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN); + +	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) { + +		if (!bfa_mem_dma_virt(seg_ptr)) +			break; + +		fcp->snsbase[idx].pa = bfa_mem_dma_phys(seg_ptr); +		fcp->snsbase[idx].kva = bfa_mem_dma_virt(seg_ptr); +		bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa); +	} + +	fcp->throttle_update_required = 1; +	bfa_fcpim_attach(fcp, bfad, cfg, pcidev); + +	bfa_iotag_attach(fcp); + +	fcp->itn_arr = (struct bfa_itn_s *) bfa_mem_kva_curp(fcp); +	bfa_mem_kva_curp(fcp) = (u8 *)fcp->itn_arr + +			(fcp->num_itns * sizeof(struct bfa_itn_s)); +	memset(fcp->itn_arr, 0, +			(fcp->num_itns * sizeof(struct bfa_itn_s))); +} + +static void +bfa_fcp_detach(struct bfa_s *bfa) +{ +} + +static void +bfa_fcp_start(struct bfa_s *bfa) +{ +	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); + +	/* +	 * bfa_init() with flash read is complete. now invalidate the stale +	 * content of lun mask like unit attention, rp tag and lp tag. +	 */ +	bfa_ioim_lm_init(fcp->bfa); +} + +static void +bfa_fcp_stop(struct bfa_s *bfa) +{ +} + +static void +bfa_fcp_iocdisable(struct bfa_s *bfa) +{ +	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); + +	bfa_fcpim_iocdisable(fcp); +} + +void +bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw) +{ +	struct bfa_fcp_mod_s	*mod = BFA_FCP_MOD(bfa); +	struct list_head	*qe; +	int	i; + +	/* Update io throttle value only once during driver load time */ +	if (!mod->throttle_update_required) +		return; + +	for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) { +		bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe); +		list_add_tail(qe, &mod->iotag_unused_q); +	} + +	if (mod->num_ioim_reqs != num_ioim_fw) { +		bfa_trc(bfa, mod->num_ioim_reqs); +		bfa_trc(bfa, num_ioim_fw); +	} + +	mod->max_ioim_reqs = max_ioim_fw; +	mod->num_ioim_reqs = num_ioim_fw; +	mod->throttle_update_required = 0; +} + +void +bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport, +		void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m)) +{ +	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); +	struct bfa_itn_s *itn; + +	itn =  BFA_ITN_FROM_TAG(fcp, rport->rport_tag); +	itn->isr = isr; +} + +/* + * Itn interrupt processing. + */ +void +bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m) +{ +	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); +	union bfi_itn_i2h_msg_u msg; +	struct bfa_itn_s *itn; + +	msg.msg = m; +	itn =  BFA_ITN_FROM_TAG(fcp, msg.create_rsp->bfa_handle); + +	if (itn->isr) +		itn->isr(bfa, m); +	else +		WARN_ON(1); +} + +void +bfa_iotag_attach(struct bfa_fcp_mod_s *fcp) +{ +	struct bfa_iotag_s *iotag; +	u16	num_io_req, i; + +	iotag = (struct bfa_iotag_s *) bfa_mem_kva_curp(fcp); +	fcp->iotag_arr = iotag; + +	INIT_LIST_HEAD(&fcp->iotag_ioim_free_q); +	INIT_LIST_HEAD(&fcp->iotag_tio_free_q); +	INIT_LIST_HEAD(&fcp->iotag_unused_q); + +	num_io_req = fcp->num_ioim_reqs + fcp->num_fwtio_reqs; +	for (i = 0; i < num_io_req; i++, iotag++) { +		memset(iotag, 0, sizeof(struct bfa_iotag_s)); +		iotag->tag = i; +		if (i < fcp->num_ioim_reqs) +			list_add_tail(&iotag->qe, &fcp->iotag_ioim_free_q); +		else +			list_add_tail(&iotag->qe, &fcp->iotag_tio_free_q); +	} + +	bfa_mem_kva_curp(fcp) = (u8 *) iotag; +} + + +/** + * To send config req, first try to use throttle value from flash + * If 0, then use driver parameter + * We need to use min(flash_val, drv_val) because + * memory allocation was done based on this cfg'd value + */ +u16 +bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param) +{ +	u16 tmp; +	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa); + +	/* +	 * If throttle value from flash is already in effect after driver is +	 * loaded then until next load, always return current value instead +	 * of actual flash value +	 */ +	if (!fcp->throttle_update_required) +		return (u16)fcp->num_ioim_reqs; + +	tmp = bfa_dconf_read_data_valid(bfa) ? bfa_fcpim_read_throttle(bfa) : 0; +	if (!tmp || (tmp > drv_cfg_param)) +		tmp = drv_cfg_param; + +	return tmp; +} + +bfa_status_t +bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value) +{ +	if (!bfa_dconf_get_min_cfg(bfa)) { +		BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.value = value; +		BFA_DCONF_MOD(bfa)->dconf->throttle_cfg.is_valid = 1; +		return BFA_STATUS_OK; +	} + +	return BFA_STATUS_FAILED; +} + +u16 +bfa_fcpim_read_throttle(struct bfa_s *bfa) +{ +	struct bfa_throttle_cfg_s *throttle_cfg = +			&(BFA_DCONF_MOD(bfa)->dconf->throttle_cfg); + +	return ((!bfa_dconf_get_min_cfg(bfa)) ? +	       ((throttle_cfg->is_valid == 1) ? (throttle_cfg->value) : 0) : 0); +} + +bfa_status_t +bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value) +{ +	/* in min cfg no commands should run. */ +	if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) || +	    (!bfa_dconf_read_data_valid(bfa))) +		return BFA_STATUS_FAILED; + +	bfa_fcpim_write_throttle(bfa, value); + +	return bfa_dconf_update(bfa); +} + +bfa_status_t +bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf) +{ +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa); +	struct bfa_defs_fcpim_throttle_s throttle; + +	if ((bfa_dconf_get_min_cfg(bfa) == BFA_TRUE) || +	    (!bfa_dconf_read_data_valid(bfa))) +		return BFA_STATUS_FAILED; + +	memset(&throttle, 0, sizeof(struct bfa_defs_fcpim_throttle_s)); + +	throttle.cur_value = (u16)(fcpim->fcp->num_ioim_reqs); +	throttle.cfg_value = bfa_fcpim_read_throttle(bfa); +	if (!throttle.cfg_value) +		throttle.cfg_value = throttle.cur_value; +	throttle.max_value = (u16)(fcpim->fcp->max_ioim_reqs); +	memcpy(buf, &throttle, sizeof(struct bfa_defs_fcpim_throttle_s)); + +	return BFA_STATUS_OK; +} diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index db53717eeb4..e693af6e593 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -24,6 +24,36 @@  #include "bfa_defs_svc.h"  #include "bfa_cs.h" +/* FCP module related definitions */ +#define BFA_IO_MAX	BFI_IO_MAX +#define BFA_FWTIO_MAX	2000 + +struct bfa_fcp_mod_s; +struct bfa_iotag_s { +	struct list_head	qe;	/* queue element	*/ +	u16	tag;			/* FW IO tag		*/ +}; + +struct bfa_itn_s { +	bfa_isr_func_t isr; +}; + +void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport, +		void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m)); +void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m); +void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp); +void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw, u16 max_ioim_fw); + +#define BFA_FCP_MOD(_hal)	(&(_hal)->modules.fcp_mod) +#define BFA_MEM_FCP_KVA(__bfa)	(&(BFA_FCP_MOD(__bfa)->kva_seg)) +#define BFA_IOTAG_FROM_TAG(_fcp, _tag)	\ +	(&(_fcp)->iotag_arr[(_tag & BFA_IOIM_IOTAG_MASK)]) +#define BFA_ITN_FROM_TAG(_fcp, _tag)	\ +	((_fcp)->itn_arr + ((_tag) & ((_fcp)->num_itns - 1))) +#define BFA_SNSINFO_FROM_TAG(_fcp, _tag) \ +	bfa_mem_get_dmabuf_kva(_fcp, (_tag & BFA_IOIM_IOTAG_MASK),	\ +	BFI_IOIM_SNSLEN) +  #define BFA_ITNIM_MIN   32  #define BFA_ITNIM_MAX   1024 @@ -41,7 +71,7 @@  	(__itnim->ioprofile.iocomps[__index]++)  #define BFA_IOIM_RETRY_TAG_OFFSET 11 -#define BFA_IOIM_RETRY_TAG_MASK 0x07ff /* 2K IOs */ +#define BFA_IOIM_IOTAG_MASK 0x07ff /* 2K IOs */  #define BFA_IOIM_RETRY_MAX 7  /* Buckets are are 512 bytes to 2MB */ @@ -51,14 +81,22 @@ bfa_ioim_get_index(u32 n) {  	if (n >= (1UL)<<22)  		return BFA_IOBUCKET_MAX - 1;  	n >>= 8; -	if (n >= (1UL)<<16) -		n >>= 16; pos += 16; -	if (n >= 1 << 8) -		n >>= 8; pos += 8; -	if (n >= 1 << 4) -		n >>= 4; pos += 4; -	if (n >= 1 << 2) -		n >>= 2; pos += 2; +	if (n >= (1UL)<<16) { +		n >>= 16; +		pos += 16; +	} +	if (n >= 1 << 8) { +		n >>= 8; +		pos += 8; +	} +	if (n >= 1 << 4) { +		n >>= 4; +		pos += 4; +	} +	if (n >= 1 << 2) { +		n >>= 2; +		pos += 2; +	}  	if (n >= 1 << 1)  		pos += 1; @@ -75,35 +113,54 @@ struct bfad_tskim_s;  typedef void    (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim); -struct bfa_fcpim_mod_s { +struct bfa_fcpim_s {  	struct bfa_s		*bfa; +	struct bfa_fcp_mod_s	*fcp;  	struct bfa_itnim_s	*itnim_arr;  	struct bfa_ioim_s	*ioim_arr;  	struct bfa_ioim_sp_s	*ioim_sp_arr;  	struct bfa_tskim_s	*tskim_arr; -	struct bfa_dma_s	snsbase;  	int			num_itnims; -	int			num_ioim_reqs;  	int			num_tskim_reqs;  	u32			path_tov;  	u16			q_depth;  	u8			reqq;		/*  Request queue to be used */ -	u8			rsvd;  	struct list_head	itnim_q;	/*  queue of active itnim */ -	struct list_head	ioim_free_q;	/*  free IO resources	*/  	struct list_head	ioim_resfree_q; /*  IOs waiting for f/w */  	struct list_head	ioim_comp_q;	/*  IO global comp Q	*/  	struct list_head	tskim_free_q; -	u32		ios_active;	/*  current active IOs	*/ -	u32		delay_comp; +	struct list_head	tskim_unused_q;	/* Unused tskim Q */ +	u32			ios_active;	/*  current active IOs	*/ +	u32			delay_comp;  	struct bfa_fcpim_del_itn_stats_s del_itn_stats;  	bfa_boolean_t		ioredirect;  	bfa_boolean_t		io_profile; -	u32		io_profile_start_time; +	u32			io_profile_start_time;  	bfa_fcpim_profile_t     profile_comp;  	bfa_fcpim_profile_t     profile_start;  }; +/* Max FCP dma segs required */ +#define BFA_FCP_DMA_SEGS	BFI_IOIM_SNSBUF_SEGS + +struct bfa_fcp_mod_s { +	struct bfa_s		*bfa; +	struct list_head	iotag_ioim_free_q;	/* free IO resources */ +	struct list_head	iotag_tio_free_q;	/* free IO resources */ +	struct list_head	iotag_unused_q;	/* unused IO resources*/ +	struct bfa_iotag_s	*iotag_arr; +	struct bfa_itn_s	*itn_arr; +	int			max_ioim_reqs; +	int			num_ioim_reqs; +	int			num_fwtio_reqs; +	int			num_itns; +	struct bfa_dma_s	snsbase[BFA_FCP_DMA_SEGS]; +	struct bfa_fcpim_s	fcpim; +	struct bfa_mem_dma_s	dma_seg[BFA_FCP_DMA_SEGS]; +	struct bfa_mem_kva_s	kva_seg; +	int			throttle_update_required; +}; +  /*   * BFA IO (initiator mode)   */ @@ -111,28 +168,27 @@ struct bfa_ioim_s {  	struct list_head	qe;		/*  queue elememt	*/  	bfa_sm_t		sm;		/*  BFA ioim state machine */  	struct bfa_s		*bfa;		/*  BFA module	*/ -	struct bfa_fcpim_mod_s	*fcpim;		/*  parent fcpim module */ +	struct bfa_fcpim_s	*fcpim;		/*  parent fcpim module */  	struct bfa_itnim_s	*itnim;		/*  i-t-n nexus for this IO  */  	struct bfad_ioim_s	*dio;		/*  driver IO handle	*/ -	u16		iotag;		/*  FWI IO tag	*/ -	u16		abort_tag;	/*  unqiue abort request tag */ -	u16		nsges;		/*  number of SG elements */ -	u16		nsgpgs;		/*  number of SG pages	*/ +	u16			iotag;		/*  FWI IO tag	*/ +	u16			abort_tag;	/*  unqiue abort request tag */ +	u16			nsges;		/*  number of SG elements */ +	u16			nsgpgs;		/*  number of SG pages	*/  	struct bfa_sgpg_s	*sgpg;		/*  first SG page	*/  	struct list_head	sgpg_q;		/*  allocated SG pages	*/  	struct bfa_cb_qe_s	hcb_qe;		/*  bfa callback qelem	*/  	bfa_cb_cbfn_t		io_cbfn;	/*  IO completion handler */ -	struct bfa_ioim_sp_s *iosp;		/*  slow-path IO handling */ -	u8		reqq;		/*  Request queue for I/O */ -	u64 start_time;			/*  IO's Profile start val */ +	struct bfa_ioim_sp_s	*iosp;		/*  slow-path IO handling */ +	u8			reqq;		/*  Request queue for I/O */ +	u8			mode;		/*  IO is passthrough or not */ +	u64			start_time;	/*  IO's Profile start val */  }; -  struct bfa_ioim_sp_s {  	struct bfi_msg_s	comp_rspmsg;	/*  IO comp f/w response */ -	u8			*snsinfo;	/*  sense info for this IO   */ -	struct bfa_sgpg_wqe_s sgpg_wqe;	/*  waitq elem for sgpg	*/ -	struct bfa_reqq_wait_s reqq_wait;	/*  to wait for room in reqq */ +	struct bfa_sgpg_wqe_s	sgpg_wqe;	/*  waitq elem for sgpg	*/ +	struct bfa_reqq_wait_s	reqq_wait;	/*  to wait for room in reqq */  	bfa_boolean_t		abort_explicit;	/*  aborted by OS	*/  	struct bfa_tskim_s	*tskim;		/*  Relevant TM cmd	*/  }; @@ -143,35 +199,34 @@ struct bfa_ioim_sp_s {  struct bfa_tskim_s {  	struct list_head	qe;  	bfa_sm_t		sm; -	struct bfa_s	*bfa;	/*  BFA module  */ -	struct bfa_fcpim_mod_s  *fcpim;	/*  parent fcpim module	*/ +	struct bfa_s		*bfa;	/*  BFA module  */ +	struct bfa_fcpim_s	*fcpim;	/*  parent fcpim module	*/  	struct bfa_itnim_s	*itnim;	/*  i-t-n nexus for this IO  */ -	struct bfad_tskim_s	*dtsk;   /*  driver task mgmt cmnd	*/ -	bfa_boolean_t	notify;	/*  notify itnim on TM comp  */ -	lun_t	lun;	/*  lun if applicable	*/ -	enum fcp_tm_cmnd	tm_cmnd;	/*  task management command  */ -	u16	tsk_tag;	/*  FWI IO tag	*/ -	u8	tsecs;	/*  timeout in seconds	*/ +	struct bfad_tskim_s	*dtsk;  /*  driver task mgmt cmnd	*/ +	bfa_boolean_t		notify;	/*  notify itnim on TM comp  */ +	struct scsi_lun		lun;	/*  lun if applicable	*/ +	enum fcp_tm_cmnd	tm_cmnd; /*  task management command  */ +	u16			tsk_tag; /*  FWI IO tag	*/ +	u8			tsecs;	/*  timeout in seconds	*/  	struct bfa_reqq_wait_s  reqq_wait;   /*  to wait for room in reqq */  	struct list_head	io_q;	/*  queue of affected IOs	*/ -	struct bfa_wc_s	wc;	/*  waiting counter	*/ +	struct bfa_wc_s		wc;	/*  waiting counter	*/  	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/  	enum bfi_tskim_status   tsk_status;  /*  TM status	*/  }; -  /*   * BFA i-t-n (initiator mode)   */  struct bfa_itnim_s { -	struct list_head	qe;		/*  queue element	*/ -	bfa_sm_t	  sm;		/*  i-t-n im BFA state machine  */ -	struct bfa_s	*bfa;		/*  bfa instance	*/ -	struct bfa_rport_s *rport;	/*  bfa rport	*/ -	void	*ditn;		/*  driver i-t-n structure	*/ +	struct list_head	qe;	/*  queue element	*/ +	bfa_sm_t		sm;	/*  i-t-n im BFA state machine  */ +	struct bfa_s		*bfa;	/*  bfa instance	*/ +	struct bfa_rport_s	*rport;	/*  bfa rport	*/ +	void			*ditn;	/*  driver i-t-n structure	*/  	struct bfi_mhdr_s	mhdr;	/*  pre-built mhdr	*/ -	u8	msg_no;		/*  itnim/rport firmware handle */ -	u8	reqq;		/*  CQ for requests	*/ +	u8			msg_no;	/*  itnim/rport firmware handle */ +	u8			reqq;	/*  CQ for requests	*/  	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/  	struct list_head pending_q;	/*  queue of pending IO requests */  	struct list_head io_q;		/*  queue of active IO requests */ @@ -181,46 +236,45 @@ struct bfa_itnim_s {  	bfa_boolean_t   seq_rec;	/*  SQER supported	*/  	bfa_boolean_t   is_online;	/*  itnim is ONLINE for IO	*/  	bfa_boolean_t   iotov_active;	/*  IO TOV timer is active	 */ -	struct bfa_wc_s	wc;	/*  waiting counter	*/ -	struct bfa_timer_s timer;	/*  pending IO TOV		 */ +	struct bfa_wc_s	wc;		/*  waiting counter	*/ +	struct bfa_timer_s timer;	/*  pending IO TOV	 */  	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */ -	struct bfa_fcpim_mod_s *fcpim;	/*  fcpim module	*/ +	struct bfa_fcpim_s *fcpim;	/*  fcpim module	*/  	struct bfa_itnim_iostats_s	stats;  	struct bfa_itnim_ioprofile_s  ioprofile;  }; -  #define bfa_itnim_is_online(_itnim) ((_itnim)->is_online) -#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod) +#define BFA_FCPIM(_hal)	(&(_hal)->modules.fcp_mod.fcpim) +#define BFA_IOIM_TAG_2_ID(_iotag)	((_iotag) & BFA_IOIM_IOTAG_MASK)  #define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\ -	(&fcpim->ioim_arr[(_iotag & BFA_IOIM_RETRY_TAG_MASK)]) +	(&fcpim->ioim_arr[(_iotag & BFA_IOIM_IOTAG_MASK)])  #define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag)	\  	(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])  #define bfa_io_profile_start_time(_bfa)	\ -	(_bfa->modules.fcpim_mod.io_profile_start_time) +	((_bfa)->modules.fcp_mod.fcpim.io_profile_start_time)  #define bfa_fcpim_get_io_profile(_bfa)	\ -	(_bfa->modules.fcpim_mod.io_profile) +	((_bfa)->modules.fcp_mod.fcpim.io_profile) +#define bfa_ioim_update_iotag(__ioim) do {				\ +	uint16_t k = (__ioim)->iotag >> BFA_IOIM_RETRY_TAG_OFFSET;	\ +	k++; (__ioim)->iotag &= BFA_IOIM_IOTAG_MASK;			\ +	(__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET;		\ +} while (0)  static inline bfa_boolean_t -bfa_ioim_get_iotag(struct bfa_ioim_s *ioim) +bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)  { -	u16 k = ioim->iotag; - -	k >>= BFA_IOIM_RETRY_TAG_OFFSET; k++; - -	if (k > BFA_IOIM_RETRY_MAX) +	uint16_t k = ioim->iotag >> BFA_IOIM_RETRY_TAG_OFFSET; +	if (k < BFA_IOIM_RETRY_MAX)  		return BFA_FALSE; -	ioim->iotag &= BFA_IOIM_RETRY_TAG_MASK; -	ioim->iotag |= k<<BFA_IOIM_RETRY_TAG_OFFSET;  	return BFA_TRUE;  } +  /*   * function prototypes   */ -void	bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, -					struct bfa_meminfo_s *minfo); -void	bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim); +void	bfa_ioim_attach(struct bfa_fcpim_s *fcpim);  void	bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);  void	bfa_ioim_good_comp_isr(struct bfa_s *bfa,  					struct bfi_msg_s *msg); @@ -230,56 +284,40 @@ void	bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,  void	bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);  void	bfa_ioim_tov(struct bfa_ioim_s *ioim); -void	bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, -					struct bfa_meminfo_s *minfo); -void	bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim); +void	bfa_tskim_attach(struct bfa_fcpim_s *fcpim);  void	bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);  void	bfa_tskim_iodone(struct bfa_tskim_s *tskim);  void	bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);  void	bfa_tskim_cleanup(struct bfa_tskim_s *tskim); +void	bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw); -void	bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -					u32 *dm_len); -void	bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, -					struct bfa_meminfo_s *minfo); -void	bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim); +void	bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len); +void	bfa_itnim_attach(struct bfa_fcpim_s *fcpim);  void	bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);  void	bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);  void	bfa_itnim_iodone(struct bfa_itnim_s *itnim);  void	bfa_itnim_tskdone(struct bfa_itnim_s *itnim);  bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim); -void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim); -void bfa_ioim_profile_start(struct bfa_ioim_s *ioim); -  /*   * bfa fcpim module API functions   */ -void		bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov); +void	bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);  u16	bfa_fcpim_path_tov_get(struct bfa_s *bfa); -void		bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);  u16	bfa_fcpim_qdepth_get(struct bfa_s *bfa); -bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa, -	 struct bfa_itnim_iostats_s *modstats);  bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa, -		struct bfa_itnim_iostats_s *stats, u8 lp_tag); -bfa_status_t bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa, -	 struct bfa_fcpim_del_itn_stats_s *modstats); -bfa_status_t bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag); +			struct bfa_itnim_iostats_s *stats, u8 lp_tag);  void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats, -		struct bfa_itnim_iostats_s *itnim_stats); -bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa); -void		bfa_fcpim_set_ioredirect(struct bfa_s *bfa, -				bfa_boolean_t state); -void		bfa_fcpim_update_ioredirect(struct bfa_s *bfa); +			struct bfa_itnim_iostats_s *itnim_stats);  bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time);  bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa); +  #define bfa_fcpim_ioredirect_enabled(__bfa)				\ -	(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect) +	(((struct bfa_fcpim_s *)(BFA_FCPIM(__bfa)))->ioredirect)  #define bfa_fcpim_get_next_reqq(__bfa, __qid)				\  {									\ -	struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa);      \ +	struct bfa_fcpim_s *__fcpim = BFA_FCPIM(__bfa);      \  	__fcpim->reqq++;						\  	__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1);      \  	*(__qid) = __fcpim->reqq;					\ @@ -291,48 +329,33 @@ bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);   * bfa itnim API functions   */  struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa, -					struct bfa_rport_s *rport, void *itnim); -void		bfa_itnim_delete(struct bfa_itnim_s *itnim); -void		bfa_itnim_online(struct bfa_itnim_s *itnim, -				 bfa_boolean_t seq_rec); -void		bfa_itnim_offline(struct bfa_itnim_s *itnim); -void		bfa_itnim_get_stats(struct bfa_itnim_s *itnim, -			struct bfa_itnim_iostats_s *stats); -void		bfa_itnim_clear_stats(struct bfa_itnim_s *itnim); -bfa_status_t	bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, -		struct bfa_itnim_ioprofile_s *ioprofile); +		struct bfa_rport_s *rport, void *itnim); +void bfa_itnim_delete(struct bfa_itnim_s *itnim); +void bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec); +void bfa_itnim_offline(struct bfa_itnim_s *itnim); +void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim); +bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, +			struct bfa_itnim_ioprofile_s *ioprofile); +  #define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)  /* - *	BFA completion callback for bfa_itnim_online(). - * - * @param[in]		itnim		FCS or driver itnim instance - * - * return None + * BFA completion callback for bfa_itnim_online().   */  void	bfa_cb_itnim_online(void *itnim);  /* - *	BFA completion callback for bfa_itnim_offline(). - * - * @param[in]		itnim		FCS or driver itnim instance - * - * return None + * BFA completion callback for bfa_itnim_offline().   */  void	bfa_cb_itnim_offline(void *itnim);  void	bfa_cb_itnim_tov_begin(void *itnim);  void	bfa_cb_itnim_tov(void *itnim);  /* - *	BFA notification to FCS/driver for second level error recovery. - * + * BFA notification to FCS/driver for second level error recovery.   * Atleast one I/O request has timedout and target is unresponsive to   * repeated abort requests. Second level error recovery should be initiated   * by starting implicit logout and recovery procedures. - * - * @param[in]		itnim		FCS or driver itnim instance - * - * return None   */  void	bfa_cb_itnim_sler(void *itnim); @@ -349,10 +372,8 @@ void		bfa_ioim_start(struct bfa_ioim_s *ioim);  bfa_status_t	bfa_ioim_abort(struct bfa_ioim_s *ioim);  void		bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,  				      bfa_boolean_t iotov); - -  /* - *	I/O completion notification. + * I/O completion notification.   *   * @param[in]		dio			driver IO structure   * @param[in]		io_status		IO completion status @@ -363,39 +384,46 @@ void		bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,   *   * @return None   */ -void	bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio, -				  enum bfi_ioim_status io_status, -				  u8 scsi_status, int sns_len, -				  u8 *sns_info, s32 residue); +void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio, +			enum bfi_ioim_status io_status, +			u8 scsi_status, int sns_len, +			u8 *sns_info, s32 residue);  /* - *	I/O good completion notification. - * - * @param[in]		dio			driver IO structure - * - * @return None + * I/O good completion notification.   */ -void	bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio); +void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);  /* - *	I/O abort completion notification - * - * @param[in]		dio			driver IO that was aborted - * - * @return None + * I/O abort completion notification   */ -void	bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio); +void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);  /*   * bfa tskim API functions   */ -struct bfa_tskim_s	*bfa_tskim_alloc(struct bfa_s *bfa, -					struct bfad_tskim_s *dtsk); -void		bfa_tskim_free(struct bfa_tskim_s *tskim); -void		bfa_tskim_start(struct bfa_tskim_s *tskim, -				struct bfa_itnim_s *itnim, lun_t lun, -				enum fcp_tm_cmnd tm, u8 t_secs); -void		bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, -				  enum bfi_tskim_status tsk_status); +struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa, +			struct bfad_tskim_s *dtsk); +void bfa_tskim_free(struct bfa_tskim_s *tskim); +void bfa_tskim_start(struct bfa_tskim_s *tskim, +			struct bfa_itnim_s *itnim, struct scsi_lun lun, +			enum fcp_tm_cmnd tm, u8 t_secs); +void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, +			enum bfi_tskim_status tsk_status); + +void	bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, +			wwn_t rp_wwn, u16 rp_tag, u8 lp_tag); +bfa_status_t	bfa_fcpim_lunmask_update(struct bfa_s *bfa, u32 on_off); +bfa_status_t	bfa_fcpim_lunmask_query(struct bfa_s *bfa, void *buf); +bfa_status_t	bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, +				wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun); +bfa_status_t	bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, +				wwn_t *pwwn, wwn_t rpwwn, struct scsi_lun lun); +bfa_status_t	bfa_fcpim_lunmask_clear(struct bfa_s *bfa); +u16		bfa_fcpim_read_throttle(struct bfa_s *bfa); +bfa_status_t	bfa_fcpim_write_throttle(struct bfa_s *bfa, u16 value); +bfa_status_t	bfa_fcpim_throttle_set(struct bfa_s *bfa, u16 value); +bfa_status_t	bfa_fcpim_throttle_get(struct bfa_s *bfa, void *buf); +u16     bfa_fcpim_get_throttle_cfg(struct bfa_s *bfa, u16 drv_cfg_param);  #endif /* __BFA_FCPIM_H__ */ diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index c94502dfac6..a3ab5cce420 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -19,9 +19,10 @@   *  bfa_fcs.c BFA FCS main   */ +#include "bfad_drv.h" +#include "bfad_im.h"  #include "bfa_fcs.h"  #include "bfa_fcbuild.h" -#include "bfad_drv.h"  BFA_TRC_FILE(FCS, FCS); @@ -75,8 +76,9 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,  	fcs->bfa = bfa;  	fcs->bfad = bfad;  	fcs->min_cfg = min_cfg; +	fcs->num_rport_logins = 0; -	bfa_attach_fcs(bfa); +	bfa->fcs = BFA_TRUE;  	fcbuild_init();  	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { @@ -92,68 +94,81 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,  void  bfa_fcs_init(struct bfa_fcs_s *fcs)  { -	int		i, npbc_vports; +	int	i;  	struct bfa_fcs_mod_s  *mod; -	struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];  	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {  		mod = &fcs_modules[i];  		if (mod->modinit)  			mod->modinit(fcs);  	} -	/* Initialize pbc vports */ -	if (!fcs->min_cfg) { -		npbc_vports = -		    bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports); -		for (i = 0; i < npbc_vports; i++) -			bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]); -	}  }  /* - * Start FCS operations. + * FCS update cfg - reset the pwwn/nwwn of fabric base logical port + * with values learned during bfa_init firmware GETATTR REQ.   */  void -bfa_fcs_start(struct bfa_fcs_s *fcs) +bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)  { -	bfa_fcs_fabric_modstart(fcs); +	struct bfa_fcs_fabric_s *fabric = &fcs->fabric; +	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg; +	struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc; + +	port_cfg->nwwn = ioc->attr->nwwn; +	port_cfg->pwwn = ioc->attr->pwwn;  }  /* - *	brief - *		FCS driver details initialization. - * - *	param[in]		fcs		FCS instance - *	param[in]		driver_info	Driver Details - * - *	return None + * Stop FCS operations.   */  void -bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, -			struct bfa_fcs_driver_info_s *driver_info) +bfa_fcs_stop(struct bfa_fcs_s *fcs)  { +	bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); +	bfa_wc_up(&fcs->wc); +	bfa_fcs_fabric_modstop(fcs); +	bfa_wc_wait(&fcs->wc); +} -	fcs->driver_info = *driver_info; +/* + * fcs pbc vport initialization + */ +void +bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs) +{ +	int i, npbc_vports; +	struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS]; -	bfa_fcs_fabric_psymb_init(&fcs->fabric); +	/* Initialize pbc vports */ +	if (!fcs->min_cfg) { +		npbc_vports = +			bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports); +		for (i = 0; i < npbc_vports; i++) +			bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]); +	}  }  /*   *	brief - *		FCS FDMI Driver Parameter Initialization + *		FCS driver details initialization.   *   *	param[in]		fcs		FCS instance - *	param[in]		fdmi_enable	TRUE/FALSE + *	param[in]		driver_info	Driver Details   *   *	return None   */  void -bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable) +bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, +			struct bfa_fcs_driver_info_s *driver_info)  { -	fcs->fdmi_enabled = fdmi_enable; +	fcs->driver_info = *driver_info; +	bfa_fcs_fabric_psymb_init(&fcs->fabric); +	bfa_fcs_fabric_nsymb_init(&fcs->fabric);  } +  /*   *	brief   *		FCS instance cleanup and exit. @@ -184,18 +199,6 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)  } -void -bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod) -{ -	fcs->trcmod = trcmod; -} - -void -bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs) -{ -	bfa_wc_down(&fcs->wc); -} -  /*   * Fabric module implementation.   */ @@ -204,11 +207,14 @@ bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)  #define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */  #define bfa_fcs_fabric_set_opertype(__fabric) do {			\ -		if (bfa_fcport_get_topology((__fabric)->fcs->bfa)	\ -		    == BFA_PORT_TOPOLOGY_P2P)				\ +	if (bfa_fcport_get_topology((__fabric)->fcs->bfa)		\ +				== BFA_PORT_TOPOLOGY_P2P) {		\ +		if (fabric->fab_type == BFA_FCS_FABRIC_SWITCHED)	\  			(__fabric)->oper_type = BFA_PORT_TYPE_NPORT;	\  		else							\ -			(__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;	\ +			(__fabric)->oper_type = BFA_PORT_TYPE_P2P;	\ +	} else								\ +		(__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;		\  } while (0)  /* @@ -221,6 +227,8 @@ static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);  static void bfa_fcs_fabric_delay(void *cbarg);  static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);  static void bfa_fcs_fabric_delete_comp(void *cbarg); +static void bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric); +static void bfa_fcs_fabric_stop_comp(void *cbarg);  static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,  				      struct fchs_s *fchs, u16 len);  static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, @@ -232,31 +240,6 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,  					 u32 rsp_len,  					 u32 resid_len,  					 struct fchs_s *rspfchs); -/* - *  fcs_fabric_sm fabric state machine functions - */ - -/* - * Fabric state machine events - */ -enum bfa_fcs_fabric_event { -	BFA_FCS_FABRIC_SM_CREATE	= 1,	/*  create from driver	      */ -	BFA_FCS_FABRIC_SM_DELETE	= 2,	/*  delete from driver	      */ -	BFA_FCS_FABRIC_SM_LINK_DOWN	= 3,	/*  link down from port      */ -	BFA_FCS_FABRIC_SM_LINK_UP	= 4,	/*  link up from port	      */ -	BFA_FCS_FABRIC_SM_CONT_OP	= 5,	/*  flogi/auth continue op   */ -	BFA_FCS_FABRIC_SM_RETRY_OP	= 6,	/*  flogi/auth retry op      */ -	BFA_FCS_FABRIC_SM_NO_FABRIC	= 7,	/*  from flogi/auth	      */ -	BFA_FCS_FABRIC_SM_PERF_EVFP	= 8,	/*  from flogi/auth	      */ -	BFA_FCS_FABRIC_SM_ISOLATE	= 9,	/*  from EVFP processing     */ -	BFA_FCS_FABRIC_SM_NO_TAGGING	= 10,	/*  no VFT tagging from EVFP */ -	BFA_FCS_FABRIC_SM_DELAYED	= 11,	/*  timeout delay event      */ -	BFA_FCS_FABRIC_SM_AUTH_FAILED	= 12,	/*  auth failed	      */ -	BFA_FCS_FABRIC_SM_AUTH_SUCCESS	= 13,	/*  auth successful	      */ -	BFA_FCS_FABRIC_SM_DELCOMP	= 14,	/*  all vports deleted event */ -	BFA_FCS_FABRIC_SM_LOOPBACK	= 15,	/*  Received our own FLOGI   */ -	BFA_FCS_FABRIC_SM_START		= 16,	/*  from driver	      */ -};  static void	bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,  					 enum bfa_fcs_fabric_event event); @@ -270,14 +253,8 @@ static void	bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,  					      enum bfa_fcs_fabric_event event);  static void	bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,  				       enum bfa_fcs_fabric_event event); -static void	bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, -					      enum bfa_fcs_fabric_event event); -static void	bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, -					   enum bfa_fcs_fabric_event event);  static void	bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,  					   enum bfa_fcs_fabric_event event); -static void	bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, -					 enum bfa_fcs_fabric_event event);  static void	bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,  				       enum bfa_fcs_fabric_event event);  static void	bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, @@ -286,6 +263,10 @@ static void	bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,  					   enum bfa_fcs_fabric_event event);  static void	bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,  					   enum bfa_fcs_fabric_event event); +static void	bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric, +					   enum bfa_fcs_fabric_event event); +static void	bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric, +					  enum bfa_fcs_fabric_event event);  /*   *   Beginning state before fabric creation.   */ @@ -319,16 +300,30 @@ static void  bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,  			  enum bfa_fcs_fabric_event event)  { +	struct bfa_s	*bfa = fabric->fcs->bfa; +  	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);  	bfa_trc(fabric->fcs, event);  	switch (event) {  	case BFA_FCS_FABRIC_SM_START: -		if (bfa_fcport_is_linkup(fabric->fcs->bfa)) { +		if (!bfa_fcport_is_linkup(fabric->fcs->bfa)) { +			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); +			break; +		} +		if (bfa_fcport_get_topology(bfa) == +				BFA_PORT_TOPOLOGY_LOOP) { +			fabric->fab_type = BFA_FCS_FABRIC_LOOP; +			fabric->bport.pid = bfa_fcport_get_myalpa(bfa); +			fabric->bport.pid = bfa_hton3b(fabric->bport.pid); +			bfa_sm_set_state(fabric, +					bfa_fcs_fabric_sm_online); +			bfa_fcs_fabric_set_opertype(fabric); +			bfa_fcs_lport_online(&fabric->bport); +		} else {  			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);  			bfa_fcs_fabric_login(fabric); -		} else -			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); +		}  		break;  	case BFA_FCS_FABRIC_SM_LINK_UP: @@ -336,8 +331,8 @@ bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,  		break;  	case BFA_FCS_FABRIC_SM_DELETE: -		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); -		bfa_fcs_modexit_comp(fabric->fcs); +		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); +		bfa_fcs_fabric_delete(fabric);  		break;  	default: @@ -353,16 +348,28 @@ static void  bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,  			   enum bfa_fcs_fabric_event event)  { +	struct bfa_s	*bfa = fabric->fcs->bfa; +  	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);  	bfa_trc(fabric->fcs, event);  	switch (event) {  	case BFA_FCS_FABRIC_SM_LINK_UP: -		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); -		bfa_fcs_fabric_login(fabric); +		if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) { +			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); +			bfa_fcs_fabric_login(fabric); +			break; +		} +		fabric->fab_type = BFA_FCS_FABRIC_LOOP; +		fabric->bport.pid = bfa_fcport_get_myalpa(bfa); +		fabric->bport.pid = bfa_hton3b(fabric->bport.pid); +		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online); +		bfa_fcs_fabric_set_opertype(fabric); +		bfa_fcs_lport_online(&fabric->bport);  		break;  	case BFA_FCS_FABRIC_SM_RETRY_OP: +	case BFA_FCS_FABRIC_SM_LOOPBACK:  		break;  	case BFA_FCS_FABRIC_SM_DELETE: @@ -370,6 +377,11 @@ bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,  		bfa_fcs_fabric_delete(fabric);  		break; +	case BFA_FCS_FABRIC_SM_STOP: +		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup); +		bfa_fcs_fabric_stop(fabric); +		break; +  	default:  		bfa_sm_fault(fabric->fcs, event);  	} @@ -410,7 +422,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,  	case BFA_FCS_FABRIC_SM_LOOPBACK:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback); -		bfa_lps_discard(fabric->lps); +		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);  		bfa_fcs_fabric_set_opertype(fabric);  		break; @@ -424,12 +436,12 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,  	case BFA_FCS_FABRIC_SM_LINK_DOWN:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); -		bfa_lps_discard(fabric->lps); +		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);  		break;  	case BFA_FCS_FABRIC_SM_DELETE:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); -		bfa_lps_discard(fabric->lps); +		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);  		bfa_fcs_fabric_delete(fabric);  		break; @@ -481,7 +493,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,  	switch (event) {  	case BFA_FCS_FABRIC_SM_AUTH_FAILED:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); -		bfa_lps_discard(fabric->lps); +		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);  		break;  	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: @@ -495,7 +507,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,  	case BFA_FCS_FABRIC_SM_LINK_DOWN:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); -		bfa_lps_discard(fabric->lps); +		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);  		break;  	case BFA_FCS_FABRIC_SM_DELETE: @@ -511,7 +523,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,  /*   *   Authentication failed   */ -static void +void  bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,  			      enum bfa_fcs_fabric_event event)  { @@ -537,7 +549,7 @@ bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,  /*   *   Port is in loopback mode.   */ -static void +void  bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,  			   enum bfa_fcs_fabric_event event)  { @@ -573,7 +585,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,  	switch (event) {  	case BFA_FCS_FABRIC_SM_LINK_DOWN:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); -		bfa_lps_discard(fabric->lps); +		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);  		bfa_fcs_fabric_notify_offline(fabric);  		break; @@ -588,6 +600,9 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,  					   fabric->bb_credit);  		break; +	case BFA_FCS_FABRIC_SM_RETRY_OP: +		break; +  	default:  		bfa_sm_fault(fabric->fcs, event);  	} @@ -596,18 +611,24 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,  /*   *   Fabric is online - normal operating state.   */ -static void +void  bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,  			 enum bfa_fcs_fabric_event event)  { +	struct bfa_s	*bfa = fabric->fcs->bfa; +  	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);  	bfa_trc(fabric->fcs, event);  	switch (event) {  	case BFA_FCS_FABRIC_SM_LINK_DOWN:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); -		bfa_lps_discard(fabric->lps); -		bfa_fcs_fabric_notify_offline(fabric); +		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) { +			bfa_fcs_lport_offline(&fabric->bport); +		} else { +			bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); +			bfa_fcs_fabric_notify_offline(fabric); +		}  		break;  	case BFA_FCS_FABRIC_SM_DELETE: @@ -615,9 +636,14 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,  		bfa_fcs_fabric_delete(fabric);  		break; +	case BFA_FCS_FABRIC_SM_STOP: +		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_stopping); +		bfa_fcs_fabric_stop(fabric); +		break; +  	case BFA_FCS_FABRIC_SM_AUTH_FAILED:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); -		bfa_lps_discard(fabric->lps); +		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);  		break;  	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: @@ -677,7 +703,7 @@ bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,  	bfa_trc(fabric->fcs, event);  	wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Port is isolated due to VF_ID mismatch. "  		"PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",  		pwwn_ptr, fabric->fcs->port_vfid, @@ -697,7 +723,7 @@ bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,  	switch (event) {  	case BFA_FCS_FABRIC_SM_DELCOMP:  		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); -		bfa_fcs_modexit_comp(fabric->fcs); +		bfa_wc_down(&fabric->fcs->wc);  		break;  	case BFA_FCS_FABRIC_SM_LINK_UP: @@ -712,7 +738,71 @@ bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,  	}  } +/* + * Fabric is being stopped, awaiting vport stop completions. + */ +static void +bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric, +			   enum bfa_fcs_fabric_event event) +{ +	struct bfa_s	*bfa = fabric->fcs->bfa; + +	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); +	bfa_trc(fabric->fcs, event); + +	switch (event) { +	case BFA_FCS_FABRIC_SM_STOPCOMP: +		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) { +			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created); +		} else { +			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup); +			bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT); +		} +		break; + +	case BFA_FCS_FABRIC_SM_LINK_UP: +		break; + +	case BFA_FCS_FABRIC_SM_LINK_DOWN: +		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) +			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created); +		else +			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup); +		break; +	default: +		bfa_sm_fault(fabric->fcs, event); +	} +} + +/* + * Fabric is being stopped, cleanup without FLOGO + */ +static void +bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric, +			  enum bfa_fcs_fabric_event event) +{ +	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); +	bfa_trc(fabric->fcs, event); + +	switch (event) { +	case BFA_FCS_FABRIC_SM_STOPCOMP: +	case BFA_FCS_FABRIC_SM_LOGOCOMP: +		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created); +		bfa_wc_down(&(fabric->fcs)->wc); +		break; + +	case BFA_FCS_FABRIC_SM_LINK_DOWN: +		/* +		 * Ignore - can get this event if we get notified about IOC down +		 * before the fabric completion callbk is done. +		 */ +		break; + +	default: +		bfa_sm_fault(fabric->fcs, event); +	} +}  /*   *  fcs_fabric_private fabric private functions @@ -724,8 +814,8 @@ bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)  	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;  	port_cfg->roles = BFA_LPORT_ROLE_FCP_IM; -	port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc); -	port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc); +	port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn; +	port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;  }  /* @@ -790,6 +880,44 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)  }  /* + * Node Symbolic Name Creation for base port and all vports + */ +void +bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric) +{ +	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg; +	char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0}; +	struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info; + +	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); + +	/* Model name/number */ +	strncpy((char *)&port_cfg->node_sym_name, model, +		BFA_FCS_PORT_SYMBNAME_MODEL_SZ); +	strncat((char *)&port_cfg->node_sym_name, +			BFA_FCS_PORT_SYMBNAME_SEPARATOR, +			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + +	/* Driver Version */ +	strncat((char *)&port_cfg->node_sym_name, (char *)driver_info->version, +		BFA_FCS_PORT_SYMBNAME_VERSION_SZ); +	strncat((char *)&port_cfg->node_sym_name, +			BFA_FCS_PORT_SYMBNAME_SEPARATOR, +			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + +	/* Host machine name */ +	strncat((char *)&port_cfg->node_sym_name, +		(char *)driver_info->host_machine_name, +		BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ); +	strncat((char *)&port_cfg->node_sym_name, +			BFA_FCS_PORT_SYMBNAME_SEPARATOR, +			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + +	/* null terminate */ +	port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0; +} + +/*   * bfa lps login completion callback   */  void @@ -813,7 +941,7 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)  		return;  	case BFA_STATUS_EPROTOCOL: -		switch (bfa_lps_get_extstatus(fabric->lps)) { +		switch (fabric->lps->ext_status) {  		case BFA_EPROTO_BAD_ACCEPT:  			fabric->stats.flogi_acc_err++;  			break; @@ -840,26 +968,27 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)  		return;  	} -	fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps); +	fabric->bb_credit = fabric->lps->pr_bbcred;  	bfa_trc(fabric->fcs, fabric->bb_credit); -	if (!bfa_lps_is_brcd_fabric(fabric->lps)) -		fabric->fabric_name =  bfa_lps_get_peer_nwwn(fabric->lps); +	if (!(fabric->lps->brcd_switch)) +		fabric->fabric_name =  fabric->lps->pr_nwwn;  	/*  	 * Check port type. It should be 1 = F-port.  	 */ -	if (bfa_lps_is_fport(fabric->lps)) { -		fabric->bport.pid = bfa_lps_get_pid(fabric->lps); -		fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps); -		fabric->is_auth = bfa_lps_is_authreq(fabric->lps); +	if (fabric->lps->fport) { +		fabric->bport.pid = fabric->lps->lp_pid; +		fabric->is_npiv = fabric->lps->npiv_en; +		fabric->is_auth = fabric->lps->auth_req;  		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);  	} else {  		/*  		 * Nport-2-Nport direct attached  		 */  		fabric->bport.port_topo.pn2n.rem_port_wwn = -			bfa_lps_get_peer_pwwn(fabric->lps); +			fabric->lps->pr_pwwn; +		fabric->fab_type = BFA_FCS_FABRIC_N2N;  		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);  	} @@ -877,8 +1006,6 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)  	struct bfa_lport_cfg_s	*pcfg = &fabric->bport.port_cfg;  	u8			alpa = 0; -	if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) -		alpa = bfa_fcport_get_myalpa(bfa);  	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),  		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd); @@ -940,6 +1067,28 @@ bfa_fcs_fabric_delay(void *cbarg)  }  /* + * Stop all vports and wait for vport stop completions. + */ +static void +bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric) +{ +	struct bfa_fcs_vport_s *vport; +	struct list_head	*qe, *qen; + +	bfa_wc_init(&fabric->stop_wc, bfa_fcs_fabric_stop_comp, fabric); + +	list_for_each_safe(qe, qen, &fabric->vport_q) { +		vport = (struct bfa_fcs_vport_s *) qe; +		bfa_wc_up(&fabric->stop_wc); +		bfa_fcs_vport_fcs_stop(vport); +	} + +	bfa_wc_up(&fabric->stop_wc); +	bfa_fcs_lport_stop(&fabric->bport); +	bfa_wc_wait(&fabric->stop_wc); +} + +/*   * Delete all vports and wait for vport delete completions.   */  static void @@ -965,6 +1114,14 @@ bfa_fcs_fabric_delete_comp(void *cbarg)  	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);  } +static void +bfa_fcs_fabric_stop_comp(void *cbarg) +{ +	struct bfa_fcs_fabric_s *fabric = cbarg; + +	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOPCOMP); +} +  /*   *  fcs_fabric_public fabric public functions   */ @@ -987,7 +1144,7 @@ bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)  	INIT_LIST_HEAD(&fabric->vport_q);  	INIT_LIST_HEAD(&fabric->vf_q);  	fabric->lps = bfa_lps_alloc(fcs->bfa); -	bfa_assert(fabric->lps); +	WARN_ON(!fabric->lps);  	/*  	 * Initialize fabric delete completion handler. Fabric deletion is @@ -1026,43 +1183,31 @@ bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)  }  /* - * Fabric module start -- kick starts FCS actions + * Fabric module stop -- stop FCS actions   */  void -bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs) +bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs)  {  	struct bfa_fcs_fabric_s *fabric;  	bfa_trc(fcs, 0);  	fabric = &fcs->fabric; -	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START); +	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOP);  }  /* - *   Suspend fabric activity as part of driver suspend. + * Fabric module start -- kick starts FCS actions   */  void -bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs) -{ -} - -bfa_boolean_t -bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric) +bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)  { -	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback); -} +	struct bfa_fcs_fabric_s *fabric; -bfa_boolean_t -bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric) -{ -	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed); +	bfa_trc(fcs, 0); +	fabric = &fcs->fabric; +	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);  } -enum bfa_port_type -bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric) -{ -	return fabric->oper_type; -}  /*   *   Link up notification from BFA physical port module. @@ -1123,43 +1268,9 @@ bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,  	bfa_wc_down(&fabric->wc);  } -/* - *   Base port is deleted. - */ -void -bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric) -{ -	bfa_wc_down(&fabric->wc); -} - - -/* - *    Check if fabric is online. - * - *   param[in] fabric - Fabric instance. This can be a base fabric or vf. - * - *   @return  TRUE/FALSE - */ -int -bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric) -{ -	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online); -}  /* - *	brief - * - */ -bfa_status_t -bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs, -		     struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv) -{ -	bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit); -	return BFA_STATUS_OK; -} - -/* - * Lookup for a vport withing a fabric given its pwwn + * Lookup for a vport within a fabric given its pwwn   */  struct bfa_fcs_vport_s *  bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn) @@ -1176,18 +1287,6 @@ bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)  	return NULL;  } -/* - *    In a given fabric, return the number of lports. - * - *   param[in] fabric - Fabric instance. This can be a base fabric or vf. - * - *   @return : 1 or more. - */ -u16 -bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric) -{ -	return fabric->num_vports; -}  /*   *  Get OUI of the attached switch. @@ -1207,7 +1306,7 @@ bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)  	u8 *tmp;  	u16 oui; -	fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps); +	fab_nwwn = fabric->lps->pr_nwwn;  	tmp = (u8 *)&fab_nwwn;  	oui = (tmp[3] << 8) | tmp[4]; @@ -1235,7 +1334,7 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,  	 * external loopback cable is in place. Our own FLOGI frames are  	 * sometimes looped back when switch port gets temporarily bypassed.  	 */ -	if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) && +	if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&  	    (els_cmd->els_code == FC_ELS_FLOGI) &&  	    (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {  		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK); @@ -1245,7 +1344,7 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,  	/*  	 * FLOGI/EVFP exchanges should be consumed by base fabric.  	 */ -	if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) { +	if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {  		bfa_trc(fabric->fcs, pid);  		bfa_fcs_fabric_process_uf(fabric, fchs, len);  		return; @@ -1276,8 +1375,11 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,  			return;  		}  	} -	bfa_trc(fabric->fcs, els_cmd->els_code); -	bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len); + +	if (!bfa_fcs_fabric_is_switched(fabric)) +		bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len); + +	bfa_trc(fabric->fcs, fchs->type);  }  /* @@ -1350,7 +1452,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)  	u16	reqlen;  	struct fchs_s	fchs; -	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs); +	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs, BFA_FALSE);  	/*  	 * Do not expect this failure -- expect remote node to retry  	 */ @@ -1358,13 +1460,13 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)  		return;  	reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), -				    bfa_os_hton3b(FC_FABRIC_PORT), +				    bfa_hton3b(FC_FABRIC_PORT),  				    n2n_port->reply_oxid, pcfg->pwwn,  				    pcfg->nwwn,  				    bfa_fcport_get_maxfrsize(bfa), -				    bfa_fcport_get_rx_bbcredit(bfa)); +				    bfa_fcport_get_rx_bbcredit(bfa), 0); -	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps), +	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,  		      BFA_FALSE, FC_CLASS_3,  		      reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,  		      FC_MAX_PDUSZ, 0); @@ -1383,6 +1485,29 @@ bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,  	bfa_trc(fabric->fcs, status);  } + +/* + * Send AEN notification + */ +static void +bfa_fcs_fabric_aen_post(struct bfa_fcs_lport_s *port, +			enum bfa_port_aen_event event) +{ +	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad; +	struct bfa_aen_entry_s  *aen_entry; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	aen_entry->aen_data.port.pwwn = bfa_fcs_lport_get_pwwn(port); +	aen_entry->aen_data.port.fwwn = bfa_fcs_lport_get_fabric_name(port); + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq, +				  BFA_AEN_CAT_PORT, event); +} +  /*   *   * @param[in] fabric - fabric @@ -1411,12 +1536,21 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,  		wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));  		wwn2str(fwwn_ptr,  			bfa_fcs_lport_get_fabric_name(&fabric->bport)); -		BFA_LOG(KERN_WARNING, bfad, log_level, +		BFA_LOG(KERN_WARNING, bfad, bfa_log_level,  			"Base port WWN = %s Fabric WWN = %s\n",  			pwwn_ptr, fwwn_ptr); +		bfa_fcs_fabric_aen_post(&fabric->bport, +				BFA_PORT_AEN_FABRIC_NAME_CHANGE);  	}  } +void +bfa_cb_lps_flogo_comp(void *bfad, void *uarg) +{ +	struct bfa_fcs_fabric_s *fabric = uarg; +	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOGOCOMP); +} +  /*   *	Returns FCS vf structure for a given vf_id.   * @@ -1436,6 +1570,45 @@ bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)  }  /* + *	Return the list of local logical ports present in the given VF. + * + *	@param[in]	vf	vf for which logical ports are returned + *	@param[out]	lpwwn	returned logical port wwn list + *	@param[in,out]	nlports in:size of lpwwn list; + *				out:total elements present, + *				actual elements returned is limited by the size + */ +void +bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports) +{ +	struct list_head *qe; +	struct bfa_fcs_vport_s *vport; +	int	i = 0; +	struct bfa_fcs_s	*fcs; + +	if (vf == NULL || lpwwn == NULL || *nlports == 0) +		return; + +	fcs = vf->fcs; + +	bfa_trc(fcs, vf->vf_id); +	bfa_trc(fcs, (uint32_t) *nlports); + +	lpwwn[i++] = vf->bport.port_cfg.pwwn; + +	list_for_each(qe, &vf->vport_q) { +		if (i >= *nlports) +			break; + +		vport = (struct bfa_fcs_vport_s *) qe; +		lpwwn[i++] = vport->lport.port_cfg.pwwn; +	} + +	bfa_trc(fcs, i); +	*nlports = i; +} + +/*   * BFA FCS PPORT ( physical port)   */  static void @@ -1455,7 +1628,7 @@ bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)  		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  	}  } @@ -1502,7 +1675,7 @@ bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)  		 * drop frame if vfid is unknown  		 */  		if (!fabric) { -			bfa_assert(0); +			WARN_ON(1);  			bfa_stats(fcs, uf.vfid_unknown);  			bfa_uf_free(uf);  			return; diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 9cb6a55977c..42bcb970445 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -27,6 +27,22 @@  #define BFA_FCS_OS_STR_LEN		64  /* + *  lps_pvt BFA LPS private functions + */ + +enum bfa_lps_event { +	BFA_LPS_SM_LOGIN	= 1,	/* login request from user      */ +	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user     */ +	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout */ +	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue  */ +	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user         */ +	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline              */ +	BFA_LPS_SM_RX_CVL	= 7,	/* Rx clear virtual link        */ +	BFA_LPS_SM_SET_N2N_PID  = 8,	/* Set assigned PID for n2n */ +}; + + +/*   * !!! Only append to the enums defined here to avoid any versioning   * !!! needed between trace utility and driver version   */ @@ -41,15 +57,14 @@ enum {  struct bfa_fcs_s;  #define __fcs_min_cfg(__fcs)       ((__fcs)->min_cfg) -void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);  #define BFA_FCS_BRCD_SWITCH_OUI  0x051e  #define N2N_LOCAL_PID	    0x010000  #define N2N_REMOTE_PID		0x020000  #define	BFA_FCS_RETRY_TIMEOUT 2000 -#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_os_ntoh3b(pid) > 0xFFF000) ?  1 : 0) - - +#define BFA_FCS_MAX_NS_RETRIES 5 +#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_ntoh3b(pid) > 0xFFF000) ?  1 : 0) +#define BFA_FCS_MAX_RPORT_LOGINS 1024  struct bfa_fcs_lport_ns_s {  	bfa_sm_t        sm;		/*  state machine */ @@ -57,6 +72,8 @@ struct bfa_fcs_lport_ns_s {  	struct bfa_fcs_lport_s *port;	/*  parent port */  	struct bfa_fcxp_s *fcxp;  	struct bfa_fcxp_wqe_s fcxp_wqe; +	u8	num_rnnid_retries; +	u8	num_rsnn_nn_retries;  }; @@ -101,15 +118,15 @@ struct bfa_fcs_lport_fab_s {  #define	MAX_ALPA_COUNT	127  struct bfa_fcs_lport_loop_s { -	u8         num_alpa;	/*  Num of ALPA entries in the map */ -	u8         alpa_pos_map[MAX_ALPA_COUNT];	/*  ALPA Positional -							 *Map */ +	u8	num_alpa;	/*  Num of ALPA entries in the map */ +	u8	alpabm_valid;	/* alpa bitmap valid or not (1 or 0) */ +	u8	alpa_pos_map[MAX_ALPA_COUNT]; /*  ALPA Positional Map */  	struct bfa_fcs_lport_s *port;	/*  parent port */  };  struct bfa_fcs_lport_n2n_s {  	u32        rsvd; -	u16        reply_oxid;	/*  ox_id from the req flogi to be +	__be16     reply_oxid;	/*  ox_id from the req flogi to be  					 *used in flogi acc */  	wwn_t           rem_port_wwn;	/*  Attached port's wwn */  }; @@ -158,6 +175,7 @@ enum bfa_fcs_fabric_type {  	BFA_FCS_FABRIC_UNKNOWN = 0,  	BFA_FCS_FABRIC_SWITCHED = 1,  	BFA_FCS_FABRIC_N2N = 2, +	BFA_FCS_FABRIC_LOOP = 3,  }; @@ -190,6 +208,7 @@ struct bfa_fcs_fabric_s {  	struct bfa_lps_s	*lps;	/*  lport login services	*/  	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];  					/*  attached fabric's ip addr  */ +	struct bfa_wc_s stop_wc;	/*  wait counter for stop */  };  #define bfa_fcs_fabric_npiv_capable(__f)    ((__f)->is_npiv) @@ -224,19 +243,19 @@ struct bfa_fcs_fabric_s;   *  Symbolic Name.   *   *  Physical Port's symbolic name Format : (Total 128 bytes) - *  Adapter Model number/name : 12 bytes + *  Adapter Model number/name : 16 bytes   *  Driver Version     : 10 bytes   *  Host Machine Name  : 30 bytes - *  Host OS Info	   : 48 bytes + *  Host OS Info	   : 44 bytes   *  Host OS PATCH Info : 16 bytes   *  ( remaining 12 bytes reserved to be used for separator)   */  #define BFA_FCS_PORT_SYMBNAME_SEPARATOR			" | " -#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ			12 +#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ			16  #define BFA_FCS_PORT_SYMBNAME_VERSION_SZ		10  #define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ		30 -#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ			48 +#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ			44  #define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ		16  /* @@ -246,6 +265,7 @@ struct bfa_fcs_fabric_s;  #define bfa_fcs_lport_get_pwwn(_lport)	((_lport)->port_cfg.pwwn)  #define bfa_fcs_lport_get_nwwn(_lport)	((_lport)->port_cfg.nwwn)  #define bfa_fcs_lport_get_psym_name(_lport)	((_lport)->port_cfg.sym_name) +#define bfa_fcs_lport_get_nsym_name(_lport) ((_lport)->port_cfg.node_sym_name)  #define bfa_fcs_lport_is_initiator(_lport)			\  	((_lport)->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)  #define bfa_fcs_lport_get_nrports(_lport)	\ @@ -268,15 +288,15 @@ bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)  bfa_boolean_t   bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);  struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs); -void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, -			      wwn_t rport_wwns[], int *nrports); - +void bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port, +			struct bfa_rport_qualifier_s rport[], int *nrports);  wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,  			      int index, int nrports, bfa_boolean_t bwwn);  struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,  					    u16 vf_id, wwn_t lpwwn); +void bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, char *symname);  void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,  			    struct bfa_lport_info_s *port_info);  void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port, @@ -306,27 +326,33 @@ void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,  void            bfa_fcs_lport_online(struct bfa_fcs_lport_s *port);  void            bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);  void            bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port); +void		bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port);  struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(  		struct bfa_fcs_lport_s *port, u32 pid); +struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_old_pid( +		struct bfa_fcs_lport_s *port, u32 pid);  struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(  		struct bfa_fcs_lport_s *port, wwn_t pwwn);  struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(  		struct bfa_fcs_lport_s *port, wwn_t nwwn); +struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_qualifier( +		struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 pid);  void            bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,  				       struct bfa_fcs_rport_s *rport);  void            bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,  				       struct bfa_fcs_rport_s *rport); -void bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs); -void bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs);  void            bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);  void            bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);  void            bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);  void            bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port); +void		bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, +				struct bfa_fcxp_s *fcxp_alloced);  void            bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);  void            bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport); -void            bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport); +void            bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *vport);  void            bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,  					      struct fchs_s *rx_frame, u32 len); +void		bfa_fcs_lport_lip_scn_online(bfa_fcs_lport_t *port);  struct bfa_fcs_vport_s {  	struct list_head		qe;		/*  queue elem	*/ @@ -359,9 +385,6 @@ bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);  bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);  void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,  			    struct bfa_vport_attr_s *vport_attr); -void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, -			     struct bfa_vport_stats_s *vport_stats); -void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);  struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,  					     u16 vf_id, wwn_t vpwwn);  void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport); @@ -369,6 +392,8 @@ void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);  void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);  void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);  void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport); +void bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport); +void bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport);  #define BFA_FCS_RPORT_DEF_DEL_TIMEOUT	90	/* in secs */  #define BFA_FCS_RPORT_MAX_RETRIES	(5) @@ -405,11 +430,13 @@ struct bfa_fcs_rport_s {  	struct bfa_fcs_s	*fcs;	/*  fcs instance */  	struct bfad_rport_s	*rp_drv;	/*  driver peer instance */  	u32	pid;	/*  port ID of rport */ +	u32	old_pid;	/* PID before rport goes offline */  	u16	maxfrsize;	/*  maximum frame size */ -	u16	reply_oxid;	/*  OX_ID of inbound requests */ +	__be16	reply_oxid;	/*  OX_ID of inbound requests */  	enum fc_cos	fc_cos;	/*  FC classes of service supp */  	bfa_boolean_t	cisc;	/*  CISC capable device */  	bfa_boolean_t	prlo;	/*  processing prlo or LOGO */ +	bfa_boolean_t	plogi_pending;	/* Rx Plogi Pending */  	wwn_t	pwwn;	/*  port wwn of rport */  	wwn_t	nwwn;	/*  node wwn of rport */  	struct bfa_rport_symname_s psym_name; /*  port symbolic name  */ @@ -426,6 +453,7 @@ struct bfa_fcs_rport_s {  	struct bfa_rport_stats_s stats;	/*  rport stats */  	enum bfa_rport_function	scsi_function;  /*  Initiator/Target */  	struct bfa_fcs_rpf_s rpf;	/* Rport features module */ +	bfa_boolean_t   scn_online;	/* SCN online flag */  };  static inline struct bfa_rport_s * @@ -437,32 +465,20 @@ bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)  /*   * bfa fcs rport API functions   */ -bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn, -			       struct bfa_fcs_rport_s *rport, -			       struct bfad_rport_s *rport_drv); -bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);  void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, -			    struct bfa_rport_attr_s *attr); -void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport, -			     struct bfa_rport_stats_s *stats); -void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport); +			struct bfa_rport_attr_s *attr);  struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,  					     wwn_t rpwwn);  struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(  	struct bfa_fcs_lport_s *port, wwn_t rnwwn);  void bfa_fcs_rport_set_del_timeout(u8 rport_tmo); - -void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, -			     enum bfa_port_speed speed); +void bfa_fcs_rport_set_max_logins(u32 max_logins);  void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,  	 struct fchs_s *fchs, u16 len);  void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);  struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_lport_s *port,  	 u32 pid); -void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport); -void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport); -void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);  void bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,  			 struct fc_logi_s *plogi_rsp);  void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, @@ -470,10 +486,8 @@ void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port,  				struct fc_logi_s *plogi);  void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,  			 struct fc_logi_s *plogi); -void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport); -void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id); +void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id); -void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);  void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);  void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);  int  bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport); @@ -504,12 +518,13 @@ struct bfa_fcs_itnim_s {  	struct bfa_fcxp_s	*fcxp;		/*  FCXP in use	*/  	struct bfa_itnim_stats_s	stats;	/*  itn statistics	*/  }; -#define bfa_fcs_fcxp_alloc(__fcs)	\ -	bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL) - -#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg) \ -	bfa_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg, \ -					NULL, 0, 0, NULL, NULL, NULL, NULL) +#define bfa_fcs_fcxp_alloc(__fcs, __req)				\ +	bfa_fcxp_req_rsp_alloc(NULL, (__fcs)->bfa, 0, 0,		\ +			       NULL, NULL, NULL, NULL, __req) +#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn,		\ +				__alloc_cbarg, __req)			\ +	bfa_fcxp_req_rsp_alloc_wait(__bfa, __wqe, __alloc_cbfn,		\ +		__alloc_cbarg, NULL, 0, 0, NULL, NULL, NULL, NULL, __req)  static inline struct bfad_port_s *  bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim) @@ -591,16 +606,30 @@ bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port,  struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);  void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);  void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim); -void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim); +void bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim);  bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);  void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);  void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,  			struct fchs_s *fchs, u16 len); -#define	BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  |	\ -				       FDMI_TRANS_SPEED_2G |	\ -				       FDMI_TRANS_SPEED_4G |	\ -				       FDMI_TRANS_SPEED_8G) +#define BFA_FCS_FDMI_SUPP_SPEEDS_4G	(FDMI_TRANS_SPEED_1G  |	\ +				FDMI_TRANS_SPEED_2G |		\ +				FDMI_TRANS_SPEED_4G) + +#define BFA_FCS_FDMI_SUPP_SPEEDS_8G	(FDMI_TRANS_SPEED_1G  |	\ +				FDMI_TRANS_SPEED_2G |		\ +				FDMI_TRANS_SPEED_4G |		\ +				FDMI_TRANS_SPEED_8G) + +#define BFA_FCS_FDMI_SUPP_SPEEDS_16G	(FDMI_TRANS_SPEED_2G  |	\ +				FDMI_TRANS_SPEED_4G |		\ +				FDMI_TRANS_SPEED_8G |		\ +				FDMI_TRANS_SPEED_16G) + +#define BFA_FCS_FDMI_SUPP_SPEEDS_10G	FDMI_TRANS_SPEED_10G + +#define BFA_FCS_FDMI_VENDOR_INFO_LEN    8 +#define BFA_FCS_FDMI_FC4_TYPE_LEN       32  /*   * HBA Attribute Block : BFA internal representation. Note : Some variable @@ -612,25 +641,39 @@ struct bfa_fcs_fdmi_hba_attr_s {  	u8         manufacturer[64];  	u8         serial_num[64];  	u8         model[16]; -	u8         model_desc[256]; +	u8         model_desc[128];  	u8         hw_version[8]; -	u8         driver_version[8]; +	u8         driver_version[BFA_VERSION_LEN];  	u8         option_rom_ver[BFA_VERSION_LEN]; -	u8         fw_version[8]; +	u8         fw_version[BFA_VERSION_LEN];  	u8         os_name[256]; -	u32        max_ct_pyld; +	__be32        max_ct_pyld; +	struct      bfa_lport_symname_s node_sym_name; +	u8     vendor_info[BFA_FCS_FDMI_VENDOR_INFO_LEN]; +	__be32    num_ports; +	wwn_t       fabric_name; +	u8     bios_ver[BFA_VERSION_LEN];  };  /*   * Port Attribute Block   */  struct bfa_fcs_fdmi_port_attr_s { -	u8         supp_fc4_types[32];	/* supported FC4 types */ -	u32        supp_speed;	/* supported speed */ -	u32        curr_speed;	/* current Speed */ -	u32        max_frm_size;	/* max frame size */ +	u8         supp_fc4_types[BFA_FCS_FDMI_FC4_TYPE_LEN]; +	__be32        supp_speed;	/* supported speed */ +	__be32        curr_speed;	/* current Speed */ +	__be32        max_frm_size;	/* max frame size */  	u8         os_device_name[256];	/* OS device Name */  	u8         host_name[256];	/* host name */ +	wwn_t       port_name; +	wwn_t       node_name; +	struct      bfa_lport_symname_s port_sym_name; +	__be32    port_type; +	enum fc_cos    scos; +	wwn_t       port_fabric_name; +	u8     port_act_fc4_type[BFA_FCS_FDMI_FC4_TYPE_LEN]; +	__be32    port_state; +	__be32    num_ports;  };  struct bfa_fcs_stats_s { @@ -661,6 +704,84 @@ struct bfa_fcs_s {  	struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */  	struct bfa_fcs_stats_s	stats;	/*  FCS statistics */  	struct bfa_wc_s		wc;	/*  waiting counter */ +	int			fcs_aen_seq; +	u32		num_rport_logins; +}; + +/* + *  fcs_fabric_sm fabric state machine functions + */ + +/* + * Fabric state machine events + */ +enum bfa_fcs_fabric_event { +	BFA_FCS_FABRIC_SM_CREATE        = 1,    /*  create from driver        */ +	BFA_FCS_FABRIC_SM_DELETE        = 2,    /*  delete from driver        */ +	BFA_FCS_FABRIC_SM_LINK_DOWN     = 3,    /*  link down from port      */ +	BFA_FCS_FABRIC_SM_LINK_UP       = 4,    /*  link up from port         */ +	BFA_FCS_FABRIC_SM_CONT_OP       = 5,    /*  flogi/auth continue op   */ +	BFA_FCS_FABRIC_SM_RETRY_OP      = 6,    /*  flogi/auth retry op      */ +	BFA_FCS_FABRIC_SM_NO_FABRIC     = 7,    /*  from flogi/auth           */ +	BFA_FCS_FABRIC_SM_PERF_EVFP     = 8,    /*  from flogi/auth           */ +	BFA_FCS_FABRIC_SM_ISOLATE       = 9,    /*  from EVFP processing     */ +	BFA_FCS_FABRIC_SM_NO_TAGGING    = 10,   /*  no VFT tagging from EVFP */ +	BFA_FCS_FABRIC_SM_DELAYED       = 11,   /*  timeout delay event      */ +	BFA_FCS_FABRIC_SM_AUTH_FAILED   = 12,   /*  auth failed       */ +	BFA_FCS_FABRIC_SM_AUTH_SUCCESS  = 13,   /*  auth successful           */ +	BFA_FCS_FABRIC_SM_DELCOMP       = 14,   /*  all vports deleted event */ +	BFA_FCS_FABRIC_SM_LOOPBACK      = 15,   /*  Received our own FLOGI   */ +	BFA_FCS_FABRIC_SM_START         = 16,   /*  from driver       */ +	BFA_FCS_FABRIC_SM_STOP		= 17,	/*  Stop from driver	*/ +	BFA_FCS_FABRIC_SM_STOPCOMP	= 18,	/*  Stop completion	*/ +	BFA_FCS_FABRIC_SM_LOGOCOMP	= 19,	/*  FLOGO completion	*/ +}; + +/* + *  fcs_rport_sm FCS rport state machine events + */ + +enum rport_event { +	RPSM_EVENT_PLOGI_SEND   = 1,    /*  new rport; start with PLOGI */ +	RPSM_EVENT_PLOGI_RCVD   = 2,    /*  Inbound PLOGI from remote port */ +	RPSM_EVENT_PLOGI_COMP   = 3,    /*  PLOGI completed to rport    */ +	RPSM_EVENT_LOGO_RCVD    = 4,    /*  LOGO from remote device     */ +	RPSM_EVENT_LOGO_IMP     = 5,    /*  implicit logo for SLER      */ +	RPSM_EVENT_FCXP_SENT    = 6,    /*  Frame from has been sent    */ +	RPSM_EVENT_DELETE       = 7,    /*  RPORT delete request        */ +	RPSM_EVENT_FAB_SCN	= 8,    /*  state change notification   */ +	RPSM_EVENT_ACCEPTED     = 9,    /*  Good response from remote device */ +	RPSM_EVENT_FAILED       = 10,   /*  Request to rport failed.    */ +	RPSM_EVENT_TIMEOUT      = 11,   /*  Rport SM timeout event      */ +	RPSM_EVENT_HCB_ONLINE  = 12,    /*  BFA rport online callback   */ +	RPSM_EVENT_HCB_OFFLINE = 13,    /*  BFA rport offline callback  */ +	RPSM_EVENT_FC4_OFFLINE = 14,    /*  FC-4 offline complete       */ +	RPSM_EVENT_ADDRESS_CHANGE = 15, /*  Rport's PID has changed     */ +	RPSM_EVENT_ADDRESS_DISC = 16,   /*  Need to Discover rport's PID */ +	RPSM_EVENT_PRLO_RCVD   = 17,    /*  PRLO from remote device     */ +	RPSM_EVENT_PLOGI_RETRY = 18,    /*  Retry PLOGI continuously */ +	RPSM_EVENT_SCN_OFFLINE = 19,	/* loop scn offline		*/ +	RPSM_EVENT_SCN_ONLINE   = 20,	/* loop scn online		*/ +	RPSM_EVENT_FC4_FCS_ONLINE = 21, /* FC-4 FCS online complete */ +}; + +/* + * fcs_itnim_sm FCS itnim state machine events + */ +enum bfa_fcs_itnim_event { +	BFA_FCS_ITNIM_SM_FCS_ONLINE = 1,        /*  rport online event */ +	BFA_FCS_ITNIM_SM_OFFLINE = 2,   /*  rport offline */ +	BFA_FCS_ITNIM_SM_FRMSENT = 3,   /*  prli frame is sent */ +	BFA_FCS_ITNIM_SM_RSP_OK = 4,    /*  good response */ +	BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /*  error response */ +	BFA_FCS_ITNIM_SM_TIMEOUT = 6,   /*  delay timeout */ +	BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /*  BFA online callback */ +	BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /*  BFA offline callback */ +	BFA_FCS_ITNIM_SM_INITIATOR = 9, /*  rport is initiator */ +	BFA_FCS_ITNIM_SM_DELETE = 10,   /*  delete event from rport */ +	BFA_FCS_ITNIM_SM_PRLO = 11,     /*  delete event from rport */ +	BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */ +	BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /* bfa rport online event */  };  /* @@ -670,18 +791,18 @@ void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,  		    struct bfad_s *bfad,  		    bfa_boolean_t min_cfg);  void bfa_fcs_init(struct bfa_fcs_s *fcs); +void bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs); +void bfa_fcs_update_cfg(struct bfa_fcs_s *fcs);  void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,  			      struct bfa_fcs_driver_info_s *driver_info); -void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);  void bfa_fcs_exit(struct bfa_fcs_s *fcs); -void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod); -void		bfa_fcs_start(struct bfa_fcs_s *fcs); +void bfa_fcs_stop(struct bfa_fcs_s *fcs);  /*   * bfa fcs vf public functions   */  bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id); -u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric); +void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);  /*   * fabric protected interface functions @@ -689,32 +810,31 @@ u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);  void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);  void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);  void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs); -void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);  void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);  void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);  void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,  	struct bfa_fcs_vport_s *vport);  void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,  	struct bfa_fcs_vport_s *vport); -int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);  struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(  		struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);  void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);  void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,  		struct fchs_s *fchs, u16 len); -bfa_boolean_t	bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric); -bfa_boolean_t	bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric); -enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);  void	bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric); -void	bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric); -bfa_status_t	bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, -			struct bfa_fcs_s *fcs, struct bfa_lport_cfg_s *port_cfg, -			struct bfad_vf_s *vf_drv); +void	bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric);  void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,  	       wwn_t fabric_name);  u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);  void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);  void bfa_fcs_port_attach(struct bfa_fcs_s *fcs); +void bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs); +void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, +			enum bfa_fcs_fabric_event event); +void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, +			enum bfa_fcs_fabric_event event); +void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, +			enum bfa_fcs_fabric_event event);  /*   * BFA FCS callback interfaces @@ -737,9 +857,6 @@ struct bfad_port_s *bfa_fcb_lport_new(struct bfad_s *bfad,  				      enum bfa_lport_role roles,  				      struct bfad_vf_s *vf_drv,  				      struct bfad_vport_s *vp_drv); -void bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles, -			  struct bfad_vf_s *vf_drv, -			  struct bfad_vport_s *vp_drv);  /*   * vport callbacks diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c index 9662bcdeb41..6dc7926a3ed 100644 --- a/drivers/scsi/bfa/bfa_fcs_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c @@ -19,9 +19,9 @@   *  fcpim.c - FCP initiator mode i-t nexus state machine   */ +#include "bfad_drv.h"  #include "bfa_fcs.h"  #include "bfa_fcbuild.h" -#include "bfad_drv.h"  #include "bfad_im.h"  BFA_TRC_FILE(FCS, FCPIM); @@ -37,24 +37,8 @@ static void	bfa_fcs_itnim_prli_response(void *fcsarg,  			 struct bfa_fcxp_s *fcxp, void *cbarg,  			    bfa_status_t req_status, u32 rsp_len,  			    u32 resid_len, struct fchs_s *rsp_fchs); - -/* - *  fcs_itnim_sm FCS itnim state machine events - */ - -enum bfa_fcs_itnim_event { -	BFA_FCS_ITNIM_SM_ONLINE = 1,	/*  rport online event */ -	BFA_FCS_ITNIM_SM_OFFLINE = 2,	/*  rport offline */ -	BFA_FCS_ITNIM_SM_FRMSENT = 3,	/*  prli frame is sent */ -	BFA_FCS_ITNIM_SM_RSP_OK = 4,	/*  good response */ -	BFA_FCS_ITNIM_SM_RSP_ERROR = 5,	/*  error response */ -	BFA_FCS_ITNIM_SM_TIMEOUT = 6,	/*  delay timeout */ -	BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /*  BFA online callback */ -	BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /*  BFA offline callback */ -	BFA_FCS_ITNIM_SM_INITIATOR = 9,	/*  rport is initiator */ -	BFA_FCS_ITNIM_SM_DELETE = 10,	/*  delete event from rport */ -	BFA_FCS_ITNIM_SM_PRLO = 11,	/*  delete event from rport */ -}; +static void	bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim, +			enum bfa_itnim_aen_event event);  static void	bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,  					 enum bfa_fcs_itnim_event event); @@ -66,6 +50,8 @@ static void	bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,  					    enum bfa_fcs_itnim_event event);  static void	bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,  					    enum bfa_fcs_itnim_event event); +static void	bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim, +					enum bfa_fcs_itnim_event event);  static void	bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,  					enum bfa_fcs_itnim_event event);  static void	bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim, @@ -96,14 +82,14 @@ bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,  	bfa_trc(itnim->fcs, event);  	switch (event) { -	case BFA_FCS_ITNIM_SM_ONLINE: +	case BFA_FCS_ITNIM_SM_FCS_ONLINE:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);  		itnim->prli_retries = 0;  		bfa_fcs_itnim_send_prli(itnim, NULL);  		break;  	case BFA_FCS_ITNIM_SM_OFFLINE: -		bfa_fcs_rport_itnim_ack(itnim->rport); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);  		break;  	case BFA_FCS_ITNIM_SM_INITIATOR: @@ -135,12 +121,13 @@ bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,  	case BFA_FCS_ITNIM_SM_INITIATOR:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);  		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);  		break;  	case BFA_FCS_ITNIM_SM_OFFLINE:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);  		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe); -		bfa_fcs_rport_itnim_ack(itnim->rport); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);  		break;  	case BFA_FCS_ITNIM_SM_DELETE: @@ -163,12 +150,13 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,  	switch (event) {  	case BFA_FCS_ITNIM_SM_RSP_OK: -		if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) { +		if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR)  			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); -		} else { -			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online); -			bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec); -		} +		else +			bfa_sm_set_state(itnim, +				bfa_fcs_itnim_sm_hal_rport_online); + +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);  		break;  	case BFA_FCS_ITNIM_SM_RSP_ERROR: @@ -178,15 +166,20 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,  				BFA_FCS_RETRY_TIMEOUT);  		break; +	case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP: +		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); +		break; +  	case BFA_FCS_ITNIM_SM_OFFLINE:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);  		bfa_fcxp_discard(itnim->fcxp); -		bfa_fcs_rport_itnim_ack(itnim->rport); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);  		break;  	case BFA_FCS_ITNIM_SM_INITIATOR:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);  		bfa_fcxp_discard(itnim->fcxp); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);  		break;  	case BFA_FCS_ITNIM_SM_DELETE: @@ -201,6 +194,44 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,  }  static void +bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim, +				enum bfa_fcs_itnim_event event) +{ +	bfa_trc(itnim->fcs, itnim->rport->pwwn); +	bfa_trc(itnim->fcs, event); + +	switch (event) { +	case BFA_FCS_ITNIM_SM_HAL_ONLINE: +		if (!itnim->bfa_itnim) +			itnim->bfa_itnim = bfa_itnim_create(itnim->fcs->bfa, +					itnim->rport->bfa_rport, itnim); + +		if (itnim->bfa_itnim) { +			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online); +			bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec); +		} else { +			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); +			bfa_sm_send_event(itnim->rport, RPSM_EVENT_DELETE); +		} + +		break; + +	case BFA_FCS_ITNIM_SM_OFFLINE: +		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); +		break; + +	case BFA_FCS_ITNIM_SM_DELETE: +		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); +		bfa_fcs_itnim_free(itnim); +		break; + +	default: +		bfa_sm_fault(itnim->fcs, event); +	} +} + +static void  bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,  			    enum bfa_fcs_itnim_event event)  { @@ -217,7 +248,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,  		} else {  			/* invoke target offline */  			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); -			bfa_fcs_rport_logo_imp(itnim->rport); +			bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);  		}  		break; @@ -225,12 +256,13 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,  	case BFA_FCS_ITNIM_SM_OFFLINE:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);  		bfa_timer_stop(&itnim->timer); -		bfa_fcs_rport_itnim_ack(itnim->rport); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);  		break;  	case BFA_FCS_ITNIM_SM_INITIATOR:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);  		bfa_timer_stop(&itnim->timer); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);  		break;  	case BFA_FCS_ITNIM_SM_DELETE: @@ -261,15 +293,15 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,  		bfa_fcb_itnim_online(itnim->itnim_drv);  		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));  		wwn2str(rpwwn_buf, itnim->rport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Target (WWN = %s) is online for initiator (WWN = %s)\n",  		rpwwn_buf, lpwwn_buf); +		bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);  		break;  	case BFA_FCS_ITNIM_SM_OFFLINE: -		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); +		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);  		bfa_itnim_offline(itnim->bfa_itnim); -		bfa_fcs_rport_itnim_ack(itnim->rport);  		break;  	case BFA_FCS_ITNIM_SM_DELETE: @@ -300,14 +332,17 @@ bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,  		bfa_itnim_offline(itnim->bfa_itnim);  		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));  		wwn2str(rpwwn_buf, itnim->rport->pwwn); -		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) -			BFA_LOG(KERN_ERR, bfad, log_level, +		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) { +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  			"Target (WWN = %s) connectivity lost for "  			"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf); -		else -			BFA_LOG(KERN_INFO, bfad, log_level, +			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT); +		} else { +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Target (WWN = %s) offlined by initiator (WWN = %s)\n",  			rpwwn_buf, lpwwn_buf); +			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE); +		}  		break;  	case BFA_FCS_ITNIM_SM_DELETE: @@ -330,7 +365,7 @@ bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,  	switch (event) {  	case BFA_FCS_ITNIM_SM_HCB_OFFLINE:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); -		bfa_fcs_rport_itnim_ack(itnim->rport); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);  		break;  	case BFA_FCS_ITNIM_SM_DELETE: @@ -358,11 +393,17 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,  	switch (event) {  	case BFA_FCS_ITNIM_SM_OFFLINE:  		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); -		bfa_fcs_rport_itnim_ack(itnim->rport); +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); +		break; + +	/* +	 * fcs_online is expected here for well known initiator ports +	 */ +	case BFA_FCS_ITNIM_SM_FCS_ONLINE: +		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);  		break;  	case BFA_FCS_ITNIM_SM_RSP_ERROR: -	case BFA_FCS_ITNIM_SM_ONLINE:  	case BFA_FCS_ITNIM_SM_INITIATOR:  		break; @@ -377,6 +418,33 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,  }  static void +bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim, +			enum bfa_itnim_aen_event event) +{ +	struct bfa_fcs_rport_s *rport = itnim->rport; +	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad; +	struct bfa_aen_entry_s	*aen_entry; + +	/* Don't post events for well known addresses */ +	if (BFA_FCS_PID_IS_WKA(rport->pid)) +		return; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	aen_entry->aen_data.itnim.vf_id = rport->port->fabric->vf_id; +	aen_entry->aen_data.itnim.ppwwn = bfa_fcs_lport_get_pwwn( +					bfa_fcs_get_base_port(itnim->fcs)); +	aen_entry->aen_data.itnim.lpwwn = bfa_fcs_lport_get_pwwn(rport->port); +	aen_entry->aen_data.itnim.rpwwn = rport->pwwn; + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq, +				  BFA_AEN_CAT_ITNIM, event); +} + +static void  bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)  {  	struct bfa_fcs_itnim_s *itnim = itnim_cbarg; @@ -388,11 +456,12 @@ bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(itnim->fcs, itnim->rport->pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		itnim->stats.fcxp_alloc_wait++;  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe, -				    bfa_fcs_itnim_send_prli, itnim); +				bfa_fcs_itnim_send_prli, itnim, BFA_TRUE);  		return;  	}  	itnim->fcxp = fcxp; @@ -445,8 +514,9 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,  			if (prli_resp->parampage.servparams.initiator) {  				bfa_trc(itnim->fcs, prli_resp->parampage.type);  				itnim->rport->scsi_function = -					 BFA_RPORT_INITIATOR; +						BFA_RPORT_INITIATOR;  				itnim->stats.prli_rsp_acc++; +				itnim->stats.initiator++;  				bfa_sm_send_event(itnim,  						  BFA_FCS_ITNIM_SM_RSP_OK);  				return; @@ -472,6 +542,10 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,  		bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);  		itnim->stats.prli_rsp_rjt++; +		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) { +			bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP); +			return; +		}  		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);  	}  } @@ -488,7 +562,11 @@ bfa_fcs_itnim_timeout(void *arg)  static void  bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)  { -	bfa_itnim_delete(itnim->bfa_itnim); +	if (itnim->bfa_itnim) { +		bfa_itnim_delete(itnim->bfa_itnim); +		itnim->bfa_itnim = NULL; +	} +  	bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);  } @@ -509,7 +587,6 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)  	struct bfa_fcs_lport_s *port = rport->port;  	struct bfa_fcs_itnim_s *itnim;  	struct bfad_itnim_s   *itnim_drv; -	struct bfa_itnim_s *bfa_itnim;  	/*  	 * call bfad to allocate the itnim @@ -527,20 +604,7 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)  	itnim->fcs = rport->fcs;  	itnim->itnim_drv = itnim_drv; -	/* -	 * call BFA to create the itnim -	 */ -	bfa_itnim = -		bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim); - -	if (bfa_itnim == NULL) { -		bfa_trc(port->fcs, rport->pwwn); -		bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv); -		bfa_assert(0); -		return NULL; -	} - -	itnim->bfa_itnim     = bfa_itnim; +	itnim->bfa_itnim     = NULL;  	itnim->seq_rec	     = BFA_FALSE;  	itnim->rec_support   = BFA_FALSE;  	itnim->conf_comp     = BFA_FALSE; @@ -570,20 +634,12 @@ bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)   * Notification from rport that PLOGI is complete to initiate FC-4 session.   */  void -bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim) +bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim)  {  	itnim->stats.onlines++; -	if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) { -		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE); -	} else { -		/* -		 *  For well known addresses, we set the itnim to initiator -		 *  state -		 */ -		itnim->stats.initiator++; -		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR); -	} +	if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) +		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HAL_ONLINE);  }  /* @@ -688,7 +744,7 @@ bfa_cb_itnim_sler(void *cb_arg)  	itnim->stats.sler++;  	bfa_trc(itnim->fcs, itnim->rport->pwwn); -	bfa_fcs_rport_logo_imp(itnim->rport); +	bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);  }  struct bfa_fcs_itnim_s * @@ -700,7 +756,7 @@ bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)  	if (!rport)  		return NULL; -	bfa_assert(rport->itnim != NULL); +	WARN_ON(rport->itnim == NULL);  	return rport->itnim;  } @@ -729,7 +785,7 @@ bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,  {  	struct bfa_fcs_itnim_s *itnim = NULL; -	bfa_assert(port != NULL); +	WARN_ON(port == NULL);  	itnim = bfa_fcs_itnim_lookup(port, rpwwn); @@ -746,7 +802,7 @@ bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)  {  	struct bfa_fcs_itnim_s *itnim = NULL; -	bfa_assert(port != NULL); +	WARN_ON(port == NULL);  	itnim = bfa_fcs_itnim_lookup(port, rpwwn); @@ -778,6 +834,6 @@ bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,  		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  	}  } diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 377cbfff6f2..ff75ef89175 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -15,13 +15,42 @@   * General Public License for more details.   */ +#include "bfad_drv.h" +#include "bfad_im.h"  #include "bfa_fcs.h"  #include "bfa_fcbuild.h"  #include "bfa_fc.h" -#include "bfad_drv.h"  BFA_TRC_FILE(FCS, PORT); +/* + * ALPA to LIXA bitmap mapping + * + * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31 + * is for L_bit (login required) and is filled as ALPA 0x00 here. + */ +static const u8 loop_alpa_map[] = { +	0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */ +	0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */ +	0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */ +	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */ + +	0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */ +	0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */ +	0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */ +	0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */ + +	0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */ +	0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */ +	0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */ +	0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */ + +	0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */ +	0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */ +	0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */ +	0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */ +}; +  static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,  					 struct fchs_s *rx_fchs, u8 reason_code,  					 u8 reason_code_expl); @@ -50,6 +79,10 @@ static void	bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);  static void	bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);  static void	bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port); +static void	bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port); +static void	bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port); +static void	bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port); +  static struct {  	void		(*init) (struct bfa_fcs_lport_s *port);  	void		(*online) (struct bfa_fcs_lport_s *port); @@ -61,7 +94,9 @@ static struct {  	bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,  			bfa_fcs_lport_fab_offline}, {  	bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online, -			bfa_fcs_lport_n2n_offline}, +			bfa_fcs_lport_n2n_offline}, { +	bfa_fcs_lport_loop_init, bfa_fcs_lport_loop_online, +			bfa_fcs_lport_loop_offline},  	};  /* @@ -74,6 +109,7 @@ enum bfa_fcs_lport_event {  	BFA_FCS_PORT_SM_OFFLINE = 3,  	BFA_FCS_PORT_SM_DELETE = 4,  	BFA_FCS_PORT_SM_DELRPORT = 5, +	BFA_FCS_PORT_SM_STOP = 6,  };  static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port, @@ -86,6 +122,8 @@ static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,  					enum bfa_fcs_lport_event event);  static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,  					enum bfa_fcs_lport_event event); +static void	bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port, +					enum bfa_fcs_lport_event event);  static void  bfa_fcs_lport_sm_uninit( @@ -123,6 +161,14 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,  		bfa_fcs_lport_deleted(port);  		break; +	case BFA_FCS_PORT_SM_STOP: +		/* If vport - send completion call back */ +		if (port->vport) +			bfa_fcs_vport_stop_comp(port->vport); +		else +			bfa_wc_down(&(port->fabric->stop_wc)); +		break; +  	case BFA_FCS_PORT_SM_OFFLINE:  		break; @@ -148,6 +194,25 @@ bfa_fcs_lport_sm_online(  		bfa_fcs_lport_offline_actions(port);  		break; +	case BFA_FCS_PORT_SM_STOP: +		__port_action[port->fabric->fab_type].offline(port); + +		if (port->num_rports == 0) { +			bfa_sm_set_state(port, bfa_fcs_lport_sm_init); +			/* If vport - send completion call back */ +			if (port->vport) +				bfa_fcs_vport_stop_comp(port->vport); +			else +				bfa_wc_down(&(port->fabric->stop_wc)); +		} else { +			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); +			list_for_each_safe(qe, qen, &port->rport_q) { +				rport = (struct bfa_fcs_rport_s *) qe; +				bfa_sm_send_event(rport, RPSM_EVENT_DELETE); +			} +		} +		break; +  	case BFA_FCS_PORT_SM_DELETE:  		__port_action[port->fabric->fab_type].offline(port); @@ -159,7 +224,7 @@ bfa_fcs_lport_sm_online(  			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);  			list_for_each_safe(qe, qen, &port->rport_q) {  				rport = (struct bfa_fcs_rport_s *) qe; -				bfa_fcs_rport_delete(rport); +				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);  			}  		}  		break; @@ -189,6 +254,23 @@ bfa_fcs_lport_sm_offline(  		bfa_fcs_lport_online_actions(port);  		break; +	case BFA_FCS_PORT_SM_STOP: +		if (port->num_rports == 0) { +			bfa_sm_set_state(port, bfa_fcs_lport_sm_init); +			/* If vport - send completion call back */ +			if (port->vport) +				bfa_fcs_vport_stop_comp(port->vport); +			else +				bfa_wc_down(&(port->fabric->stop_wc)); +		} else { +			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping); +			list_for_each_safe(qe, qen, &port->rport_q) { +				rport = (struct bfa_fcs_rport_s *) qe; +				bfa_sm_send_event(rport, RPSM_EVENT_DELETE); +			} +		} +		break; +  	case BFA_FCS_PORT_SM_DELETE:  		if (port->num_rports == 0) {  			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit); @@ -197,7 +279,7 @@ bfa_fcs_lport_sm_offline(  			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);  			list_for_each_safe(qe, qen, &port->rport_q) {  				rport = (struct bfa_fcs_rport_s *) qe; -				bfa_fcs_rport_delete(rport); +				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);  			}  		}  		break; @@ -212,6 +294,30 @@ bfa_fcs_lport_sm_offline(  }  static void +bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port, +			  enum bfa_fcs_lport_event event) +{ +	bfa_trc(port->fcs, port->port_cfg.pwwn); +	bfa_trc(port->fcs, event); + +	switch (event) { +	case BFA_FCS_PORT_SM_DELRPORT: +		if (port->num_rports == 0) { +			bfa_sm_set_state(port, bfa_fcs_lport_sm_init); +			/* If vport - send completion call back */ +			if (port->vport) +				bfa_fcs_vport_stop_comp(port->vport); +			else +				bfa_wc_down(&(port->fabric->stop_wc)); +		} +		break; + +	default: +		bfa_sm_fault(port->fcs, event); +	} +} + +static void  bfa_fcs_lport_sm_deleting(  	struct bfa_fcs_lport_s *port,  	enum bfa_fcs_lport_event event) @@ -237,6 +343,31 @@ bfa_fcs_lport_sm_deleting(   */  /* + * Send AEN notification + */ +static void +bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s *port, +			enum bfa_lport_aen_event event) +{ +	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad; +	struct bfa_aen_entry_s  *aen_entry; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	aen_entry->aen_data.lport.vf_id = port->fabric->vf_id; +	aen_entry->aen_data.lport.roles = port->port_cfg.roles; +	aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn( +					bfa_fcs_get_base_port(port->fcs)); +	aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port); + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq, +				  BFA_AEN_CAT_LPORT, event); +} + +/*   * Send a LS reject   */  static void @@ -251,7 +382,7 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,  	bfa_trc(port->fcs, rx_fchs->d_id);  	bfa_trc(port->fcs, rx_fchs->s_id); -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -265,6 +396,40 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,  }  /* + * Send a FCCT Reject + */ +static void +bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port, +	struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl) +{ +	struct fchs_s   fchs; +	struct bfa_fcxp_s *fcxp; +	struct bfa_rport_s *bfa_rport = NULL; +	int             len; +	struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1); +	struct ct_hdr_s *ct_hdr; + +	bfa_trc(port->fcs, rx_fchs->d_id); +	bfa_trc(port->fcs, rx_fchs->s_id); + +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); +	if (!fcxp) +		return; + +	ct_hdr = bfa_fcxp_get_reqbuf(fcxp); +	ct_hdr->gs_type = rx_cthdr->gs_type; +	ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type; + +	len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id, +			bfa_fcs_lport_get_fcid(port), +			rx_fchs->ox_id, reason_code, reason_code_expl); + +	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, +			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, +			FC_MAX_PDUSZ, 0); +} + +/*   * Process incoming plogi from a remote port.   */  static void @@ -309,6 +474,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,  			return;  		}  		port->pid  = rx_fchs->d_id; +		bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);  	}  	/* @@ -323,6 +489,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,  			(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),  			(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {  			port->pid  = rx_fchs->d_id; +			bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);  			rport->pid = rx_fchs->s_id;  		}  		bfa_fcs_rport_plogi(rport, rx_fchs, plogi); @@ -349,8 +516,8 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,  		 * This is a different device with the same pid. Old device  		 * disappeared. Send implicit LOGO to old device.  		 */ -		bfa_assert(rport->pwwn != plogi->port_name); -		bfa_fcs_rport_logo_imp(rport); +		WARN_ON(rport->pwwn == plogi->port_name); +		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);  		/*  		 * Inbound PLOGI from a new device (with old PID). @@ -362,7 +529,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,  	/*  	 * PLOGI crossing each other.  	 */ -	bfa_assert(rport->pwwn == WWN_NULL); +	WARN_ON(rport->pwwn != WWN_NULL);  	bfa_fcs_rport_plogi(rport, rx_fchs, plogi);  } @@ -382,7 +549,7 @@ bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,  	bfa_trc(port->fcs, rx_fchs->s_id);  	bfa_trc(port->fcs, rx_fchs->d_id); -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -427,7 +594,7 @@ bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,  	bfa_trc(port->fcs, rx_fchs->d_id);  	bfa_trc(port->fcs, rx_len); -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -491,9 +658,10 @@ bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)  	__port_action[port->fabric->fab_type].online(port);  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_WARNING, bfad, bfa_log_level,  		"Logical port online: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); +	bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE);  	bfad->bfad_flags |= BFAD_PORT_ONLINE;  } @@ -511,37 +679,41 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)  	__port_action[port->fabric->fab_type].offline(port);  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); -	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) -		BFA_LOG(KERN_ERR, bfad, log_level, +	if (bfa_sm_cmp_state(port->fabric, +			bfa_fcs_fabric_sm_online) == BFA_TRUE) { +		BFA_LOG(KERN_WARNING, bfad, bfa_log_level,  		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); -	else -		BFA_LOG(KERN_INFO, bfad, log_level, +		bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT); +	} else { +		BFA_LOG(KERN_WARNING, bfad, bfa_log_level,  		"Logical port taken offline: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); +		bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE); +	}  	list_for_each_safe(qe, qen, &port->rport_q) {  		rport = (struct bfa_fcs_rport_s *) qe; -		bfa_fcs_rport_offline(rport); +		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);  	}  }  static void  bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)  { -	bfa_assert(0); +	WARN_ON(1);  }  static void  bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)  { -	bfa_assert(0); +	WARN_ON(1);  }  static void  bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)  { -	bfa_assert(0); +	WARN_ON(1);  }  static void @@ -554,7 +726,7 @@ bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)  	bfa_trc(port->fcs, rx_fchs->d_id);  	bfa_trc(port->fcs, rx_fchs->s_id); -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -573,43 +745,18 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)  	char    lpwwn_buf[BFA_STRING_32];  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Logical port deleted: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); +	bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE);  	/* Base port will be deleted by the OS driver */ -	if (port->vport) { -		bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles, -				port->fabric->vf_drv, -				port->vport ? port->vport->vport_drv : NULL); +	if (port->vport)  		bfa_fcs_vport_delete_comp(port->vport); -	} else { -		 bfa_fcs_fabric_port_delete_comp(port->fabric); -	} -} - - - -/* - *  fcs_lport_api BFA FCS port API - */ -/* - *   Module initialization - */ -void -bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs) -{ - +	else +		bfa_wc_down(&port->fabric->wc);  } -/* - *   Module cleanup - */ -void -bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs) -{ -	bfa_fcs_modexit_comp(fcs); -}  /*   * Unsolicited frame receive handling. @@ -623,9 +770,23 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,  	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);  	bfa_stats(lport, uf_recvs); +	bfa_trc(lport->fcs, fchs->type);  	if (!bfa_fcs_lport_is_online(lport)) { -		bfa_stats(lport, uf_recv_drops); +		/* +		 * In direct attach topology, it is possible to get a PLOGI +		 * before the lport is online due to port feature +		 * (QoS/Trunk/FEC/CR), so send a rjt +		 */ +		if ((fchs->type == FC_TYPE_ELS) && +			(els_cmd->els_code == FC_ELS_PLOGI)) { +			bfa_fcs_lport_send_ls_rjt(lport, fchs, +				FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD, +				FC_LS_RJT_EXP_NO_ADDL_INFO); +			bfa_stats(lport, plogi_rcvd); +		} else +			bfa_stats(lport, uf_recv_drops); +  		return;  	} @@ -665,6 +826,16 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,  			bfa_fcs_lport_abts_acc(lport, fchs);  		return;  	} + +	if (fchs->type == FC_TYPE_SERVICES) { +		/* +		 * Unhandled FC-GS frames. Send a FC-CT Reject +		 */ +		bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP, +				CT_NS_EXP_NOADDITIONAL); +		return; +	} +  	/*  	 * look for a matching remote port ID  	 */ @@ -682,8 +853,11 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,  	 * Only handles ELS frames for now.  	 */  	if (fchs->type != FC_TYPE_ELS) { -		bfa_trc(lport->fcs, fchs->type); -		bfa_assert(0); +		bfa_trc(lport->fcs, fchs->s_id); +		bfa_trc(lport->fcs, fchs->d_id); +		/* ignore type FC_TYPE_FC_FSS */ +		if (fchs->type != FC_TYPE_FC_FSS) +			bfa_sm_fault(lport->fcs, fchs->type);  		return;  	} @@ -735,6 +909,25 @@ bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)  }  /* + * OLD_PID based Lookup for a R-Port in the Port R-Port Queue + */ +struct bfa_fcs_rport_s * +bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid) +{ +	struct bfa_fcs_rport_s *rport; +	struct list_head	*qe; + +	list_for_each(qe, &port->rport_q) { +		rport = (struct bfa_fcs_rport_s *) qe; +		if (rport->old_pid == pid) +			return rport; +	} + +	bfa_trc(port->fcs, pid); +	return NULL; +} + +/*   *   PWWN based Lookup for a R-Port in the Port R-Port Queue   */  struct bfa_fcs_rport_s * @@ -773,6 +966,26 @@ bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)  }  /* + * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue + */ +struct bfa_fcs_rport_s * +bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port, +				     wwn_t pwwn, u32 pid) +{ +	struct bfa_fcs_rport_s *rport; +	struct list_head	*qe; + +	list_for_each(qe, &port->rport_q) { +		rport = (struct bfa_fcs_rport_s *) qe; +		if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid) +			return rport; +	} + +	bfa_trc(port->fcs, pwwn); +	return NULL; +} + +/*   * Called by rport module when new rports are discovered.   */  void @@ -792,7 +1005,7 @@ bfa_fcs_lport_del_rport(  	struct bfa_fcs_lport_s *port,  	struct bfa_fcs_rport_s *rport)  { -	bfa_assert(bfa_q_is_on_q(&port->rport_q, rport)); +	WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));  	list_del(&rport->qe);  	port->num_rports--; @@ -820,6 +1033,16 @@ bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)  }  /* + * Called by fabric for base port and by vport for virtual ports + * when target mode driver is unloaded. + */ +void +bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port) +{ +	bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP); +} + +/*   * Called by fabric to delete base lport and associated resources.   *   * Called by vport to delete lport and associated resources. Should call @@ -850,8 +1073,8 @@ bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,  	lport->fcs = fcs;  	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);  	lport->vport = vport; -	lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) : -				  bfa_lps_get_tag(lport->fabric->lps); +	lport->lp_tag = (vport) ? vport->lps->bfa_tag : +				  lport->fabric->lps->bfa_tag;  	INIT_LIST_HEAD(&lport->rport_q);  	lport->num_rports = 0; @@ -878,14 +1101,26 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,  					vport ? vport->vport_drv : NULL);  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport)); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"New logical port created: WWN = %s Role = %s\n",  		lpwwn_buf, "Initiator"); +	bfa_fcs_lport_aen_post(lport, BFA_LPORT_AEN_NEW);  	bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);  	bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);  } +void +bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, +				char *symname) +{ +	strcpy(port->port_cfg.sym_name.symname, symname); + +	if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) +		bfa_fcs_lport_ns_util_send_rspn_id( +			BFA_FCS_GET_NS_FROM_PORT(port), NULL); +} +  /*   *  fcs_lport_api   */ @@ -903,10 +1138,12 @@ bfa_fcs_lport_get_attr(  	port_attr->port_cfg = port->port_cfg;  	if (port->fabric) { -		port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric); -		port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric); +		port_attr->port_type = port->fabric->oper_type; +		port_attr->loopback = bfa_sm_cmp_state(port->fabric, +				bfa_fcs_fabric_sm_loopback);  		port_attr->authfail = -			bfa_fcs_fabric_is_auth_failed(port->fabric); +			bfa_sm_cmp_state(port->fabric, +				bfa_fcs_fabric_sm_auth_failed);  		port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);  		memcpy(port_attr->fabric_ip_addr,  			bfa_fcs_lport_get_fabric_ipaddr(port), @@ -915,10 +1152,10 @@ bfa_fcs_lport_get_attr(  		if (port->vport != NULL) {  			port_attr->port_type = BFA_PORT_TYPE_VPORT;  			port_attr->fpma_mac = -				bfa_lps_get_lp_mac(port->vport->lps); +				port->vport->lps->lp_mac;  		} else {  			port_attr->fpma_mac = -				bfa_lps_get_lp_mac(port->fabric->lps); +				port->fabric->lps->lp_mac;  		}  	} else {  		port_attr->port_type = BFA_PORT_TYPE_UNKNOWN; @@ -948,7 +1185,7 @@ static void  bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)  {  	bfa_fcs_lport_ns_online(port); -	bfa_fcs_lport_scn_online(port); +	bfa_fcs_lport_fab_scn_online(port);  }  /* @@ -998,6 +1235,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)  	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,  	     sizeof(wwn_t)) > 0) {  		port->pid = N2N_LOCAL_PID; +		bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);  		/*  		 * First, check if we know the device by pwwn.  		 */ @@ -1007,7 +1245,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)  			bfa_trc(port->fcs, rport->pid);  			bfa_trc(port->fcs, rport->pwwn);  			rport->pid = N2N_REMOTE_PID; -			bfa_fcs_rport_online(rport); +			bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);  			return;  		} @@ -1017,10 +1255,10 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)  		 */  		if (port->num_rports > 0) {  			rport = bfa_fcs_lport_get_rport_by_pid(port, 0); -			bfa_assert(rport != NULL); +			WARN_ON(rport == NULL);  			if (rport) {  				bfa_trc(port->fcs, rport->pwwn); -				bfa_fcs_rport_delete(rport); +				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);  			}  		}  		bfa_fcs_rport_create(port, N2N_REMOTE_PID); @@ -1041,6 +1279,98 @@ bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)  	n2n_port->reply_oxid = 0;  } +void +bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port) +{ +	int i = 0, j = 0, bit = 0, alpa_bit = 0; +	u8 k = 0; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa); + +	port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid; +	port->pid = fcport->myalpa; +	port->pid = bfa_hton3b(port->pid); + +	for (i = 0; i < (FC_ALPA_MAX / 8); i++) { +		for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) { +			bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]); +			bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j))); +			if (bit) { +				port->port_topo.ploop.alpa_pos_map[k] = +					loop_alpa_map[(i * 8) + alpa_bit]; +				k++; +				bfa_trc(port->fcs->bfa, k); +				bfa_trc(port->fcs->bfa, +					 port->port_topo.ploop.alpa_pos_map[k]); +			} +		} +	} +	port->port_topo.ploop.num_alpa = k; +} + +/* + * Called by fcs/port to initialize Loop topology. + */ +static void +bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port) +{ +} + +/* + * Called by fcs/port to notify transition to online state. + */ +static void +bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port) +{ +	u8 num_alpa = 0, alpabm_valid = 0; +	struct bfa_fcs_rport_s *rport; +	u8 *alpa_map = NULL; +	int i = 0; +	u32 pid; + +	bfa_fcport_get_loop_attr(port); + +	num_alpa = port->port_topo.ploop.num_alpa; +	alpabm_valid = port->port_topo.ploop.alpabm_valid; +	alpa_map = port->port_topo.ploop.alpa_pos_map; + +	bfa_trc(port->fcs->bfa, port->pid); +	bfa_trc(port->fcs->bfa, num_alpa); +	if (alpabm_valid == 1) { +		for (i = 0; i < num_alpa; i++) { +			bfa_trc(port->fcs->bfa, alpa_map[i]); +			if (alpa_map[i] != bfa_hton3b(port->pid)) { +				pid = alpa_map[i]; +				bfa_trc(port->fcs->bfa, pid); +				rport = bfa_fcs_lport_get_rport_by_pid(port, +						bfa_hton3b(pid)); +				if (!rport) +					rport = bfa_fcs_rport_create(port, +						bfa_hton3b(pid)); +			} +		} +	} else { +		for (i = 0; i < MAX_ALPA_COUNT; i++) { +			if (alpa_map[i] != port->pid) { +				pid = loop_alpa_map[i]; +				bfa_trc(port->fcs->bfa, pid); +				rport = bfa_fcs_lport_get_rport_by_pid(port, +						bfa_hton3b(pid)); +				if (!rport) +					rport = bfa_fcs_rport_create(port, +						bfa_hton3b(pid)); +			} +		} +	} +} + +/* + * Called by fcs/port to notify transition to offline state. + */ +static void +bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port) +{ +} +  #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2  /* @@ -1086,6 +1416,8 @@ static void	bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,  				 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);  static void	bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,  				  struct bfa_fcs_fdmi_port_attr_s *port_attr); +u32	bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed); +  /*   *  fcs_fdmi_sm FCS FDMI state machine   */ @@ -1161,7 +1493,7 @@ bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,  		} else {  			/*  			 * For a base port, we should first register the HBA -			 * atribute. The HBA attribute also contains the base +			 * attribute. The HBA attribute also contains the base  			 *  port registration.  			 */  			bfa_sm_set_state(fdmi, @@ -1532,10 +1864,11 @@ bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->port_cfg.pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, -					bfa_fcs_lport_fdmi_send_rhba, fdmi); +				bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE);  		return;  	}  	fdmi->fcxp = fcxp; @@ -1569,6 +1902,7 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)  	struct fdmi_attr_s *attr;  	u8        *curr_ptr;  	u16        len, count; +	u16	templen;  	/*  	 * get hba attributes @@ -1594,69 +1928,69 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME); -	attr->len = sizeof(wwn_t); -	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = sizeof(wwn_t); +	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * Manufacturer  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER); -	attr->len = (u16) strlen(fcs_hba_attr->manufacturer); -	memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len); -	attr->len = fc_roundup(attr->len, sizeof(u32)); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = (u16) strlen(fcs_hba_attr->manufacturer); +	memcpy(attr->value, fcs_hba_attr->manufacturer, templen); +	templen = fc_roundup(templen, sizeof(u32)); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * Serial Number  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM); -	attr->len = (u16) strlen(fcs_hba_attr->serial_num); -	memcpy(attr->value, fcs_hba_attr->serial_num, attr->len); -	attr->len = fc_roundup(attr->len, sizeof(u32)); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = (u16) strlen(fcs_hba_attr->serial_num); +	memcpy(attr->value, fcs_hba_attr->serial_num, templen); +	templen = fc_roundup(templen, sizeof(u32)); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * Model  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL); -	attr->len = (u16) strlen(fcs_hba_attr->model); -	memcpy(attr->value, fcs_hba_attr->model, attr->len); -	attr->len = fc_roundup(attr->len, sizeof(u32)); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = (u16) strlen(fcs_hba_attr->model); +	memcpy(attr->value, fcs_hba_attr->model, templen); +	templen = fc_roundup(templen, sizeof(u32)); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * Model Desc  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC); -	attr->len = (u16) strlen(fcs_hba_attr->model_desc); -	memcpy(attr->value, fcs_hba_attr->model_desc, attr->len); -	attr->len = fc_roundup(attr->len, sizeof(u32)); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = (u16) strlen(fcs_hba_attr->model_desc); +	memcpy(attr->value, fcs_hba_attr->model_desc, templen); +	templen = fc_roundup(templen, sizeof(u32)); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * H/W Version @@ -1664,14 +1998,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)  	if (fcs_hba_attr->hw_version[0] != '\0') {  		attr = (struct fdmi_attr_s *) curr_ptr;  		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION); -		attr->len = (u16) strlen(fcs_hba_attr->hw_version); -		memcpy(attr->value, fcs_hba_attr->hw_version, attr->len); -		attr->len = fc_roundup(attr->len, sizeof(u32)); -		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -		len += attr->len; +		templen = (u16) strlen(fcs_hba_attr->hw_version); +		memcpy(attr->value, fcs_hba_attr->hw_version, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen;  		count++; -		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -					 sizeof(attr->len)); +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					 sizeof(templen));  	}  	/* @@ -1679,14 +2013,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION); -	attr->len = (u16) strlen(fcs_hba_attr->driver_version); -	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); -	attr->len = fc_roundup(attr->len, sizeof(u32)); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len;; +	templen = (u16) strlen(fcs_hba_attr->driver_version); +	memcpy(attr->value, fcs_hba_attr->driver_version, templen); +	templen = fc_roundup(templen, sizeof(u32)); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * Option Rom Version @@ -1694,29 +2028,26 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)  	if (fcs_hba_attr->option_rom_ver[0] != '\0') {  		attr = (struct fdmi_attr_s *) curr_ptr;  		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION); -		attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver); -		memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len); -		attr->len = fc_roundup(attr->len, sizeof(u32)); -		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -		len += attr->len; +		templen = (u16) strlen(fcs_hba_attr->option_rom_ver); +		memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen;  		count++; -		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -					 sizeof(attr->len)); +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					 sizeof(templen));  	} -	/* -	 * f/w Version = driver version -	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION); -	attr->len = (u16) strlen(fcs_hba_attr->driver_version); -	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); -	attr->len = fc_roundup(attr->len, sizeof(u32)); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = (u16) strlen(fcs_hba_attr->fw_version); +	memcpy(attr->value, fcs_hba_attr->fw_version, templen); +	templen = fc_roundup(templen, sizeof(u32)); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * OS Name @@ -1724,14 +2055,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)  	if (fcs_hba_attr->os_name[0] != '\0') {  		attr = (struct fdmi_attr_s *) curr_ptr;  		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME); -		attr->len = (u16) strlen(fcs_hba_attr->os_name); -		memcpy(attr->value, fcs_hba_attr->os_name, attr->len); -		attr->len = fc_roundup(attr->len, sizeof(u32)); -		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -		len += attr->len; +		templen = (u16) strlen(fcs_hba_attr->os_name); +		memcpy(attr->value, fcs_hba_attr->os_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen;  		count++; -		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -					sizeof(attr->len)); +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					sizeof(templen));  	}  	/* @@ -1739,12 +2070,73 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT); -	attr->len = sizeof(fcs_hba_attr->max_ct_pyld); -	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len); -	len += attr->len; +	templen = sizeof(fcs_hba_attr->max_ct_pyld); +	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen); +	templen = fc_roundup(templen, sizeof(u32)); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	count++; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen)); +	/* +	 * Send extended attributes ( FOS 7.1 support ) +	 */ +	if (fdmi->retry_cnt == 0) { +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODE_SYM_NAME); +		templen = sizeof(fcs_hba_attr->node_sym_name); +		memcpy(attr->value, &fcs_hba_attr->node_sym_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		count++; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_VENDOR_ID); +		templen = sizeof(fcs_hba_attr->vendor_info); +		memcpy(attr->value, &fcs_hba_attr->vendor_info, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		count++; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NUM_PORTS); +		templen = sizeof(fcs_hba_attr->num_ports); +		memcpy(attr->value, &fcs_hba_attr->num_ports, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		count++; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FABRIC_NAME); +		templen = sizeof(fcs_hba_attr->fabric_name); +		memcpy(attr->value, &fcs_hba_attr->fabric_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		count++; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_BIOS_VER); +		templen = sizeof(fcs_hba_attr->bios_ver); +		memcpy(attr->value, &fcs_hba_attr->bios_ver, templen); +		templen = fc_roundup(attr->len, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		count++; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					sizeof(templen)); +	}  	/*  	 * Update size of payload @@ -1805,10 +2197,11 @@ bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->port_cfg.pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, -					bfa_fcs_lport_fdmi_send_rprt, fdmi); +				bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);  		return;  	}  	fdmi->fcxp = fcxp; @@ -1845,6 +2238,7 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,  	u8        *curr_ptr;  	u16        len;  	u8	count = 0; +	u16	templen;  	/*  	 * get port attributes @@ -1863,54 +2257,54 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES); -	attr->len = sizeof(fcs_port_attr.supp_fc4_types); -	memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = sizeof(fcs_port_attr.supp_fc4_types); +	memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	++count;  	attr->len = -		cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +		cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * Supported Speed  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED); -	attr->len = sizeof(fcs_port_attr.supp_speed); -	memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = sizeof(fcs_port_attr.supp_speed); +	memcpy(attr->value, &fcs_port_attr.supp_speed, templen); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	++count;  	attr->len = -		cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +		cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * current Port Speed  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED); -	attr->len = sizeof(fcs_port_attr.curr_speed); -	memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = sizeof(fcs_port_attr.curr_speed); +	memcpy(attr->value, &fcs_port_attr.curr_speed, templen); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	++count; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * max frame size  	 */  	attr = (struct fdmi_attr_s *) curr_ptr;  	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE); -	attr->len = sizeof(fcs_port_attr.max_frm_size); -	memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len); -	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -	len += attr->len; +	templen = sizeof(fcs_port_attr.max_frm_size); +	memcpy(attr->value, &fcs_port_attr.max_frm_size, templen); +	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +	len += templen;  	++count; -	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -			     sizeof(attr->len)); +	attr->len = cpu_to_be16(templen + sizeof(attr->type) + +			     sizeof(templen));  	/*  	 * OS Device Name @@ -1918,14 +2312,14 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,  	if (fcs_port_attr.os_device_name[0] != '\0') {  		attr = (struct fdmi_attr_s *) curr_ptr;  		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME); -		attr->len = (u16) strlen(fcs_port_attr.os_device_name); -		memcpy(attr->value, fcs_port_attr.os_device_name, attr->len); -		attr->len = fc_roundup(attr->len, sizeof(u32)); -		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -		len += attr->len; +		templen = (u16) strlen(fcs_port_attr.os_device_name); +		memcpy(attr->value, fcs_port_attr.os_device_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen;  		++count; -		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -					sizeof(attr->len)); +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +					sizeof(templen));  	}  	/*  	 * Host Name @@ -1933,14 +2327,121 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,  	if (fcs_port_attr.host_name[0] != '\0') {  		attr = (struct fdmi_attr_s *) curr_ptr;  		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME); -		attr->len = (u16) strlen(fcs_port_attr.host_name); -		memcpy(attr->value, fcs_port_attr.host_name, attr->len); -		attr->len = fc_roundup(attr->len, sizeof(u32)); -		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; -		len += attr->len; +		templen = (u16) strlen(fcs_port_attr.host_name); +		memcpy(attr->value, fcs_port_attr.host_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				sizeof(templen)); +	} + +	if (fdmi->retry_cnt == 0) { +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_NODE_NAME); +		templen = sizeof(fcs_port_attr.node_name); +		memcpy(attr->value, &fcs_port_attr.node_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				 sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NAME); +		templen = sizeof(fcs_port_attr.port_name); +		memcpy(attr->value, &fcs_port_attr.port_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				 sizeof(templen)); + +		if (fcs_port_attr.port_sym_name.symname[0] != '\0') { +			attr = (struct fdmi_attr_s *) curr_ptr; +			attr->type = +				cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SYM_NAME); +			templen = sizeof(fcs_port_attr.port_sym_name); +			memcpy(attr->value, +				&fcs_port_attr.port_sym_name, templen); +			templen = fc_roundup(templen, sizeof(u32)); +			curr_ptr += sizeof(attr->type) + +					sizeof(templen) + templen; +			len += templen; +			++count; +			attr->len = cpu_to_be16(templen + +				sizeof(attr->type) + sizeof(templen)); +		} + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_TYPE); +		templen = sizeof(fcs_port_attr.port_type); +		memcpy(attr->value, &fcs_port_attr.port_type, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				 sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_COS); +		templen = sizeof(fcs_port_attr.scos); +		memcpy(attr->value, &fcs_port_attr.scos, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				 sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FAB_NAME); +		templen = sizeof(fcs_port_attr.port_fabric_name); +		memcpy(attr->value, &fcs_port_attr.port_fabric_name, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				 sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_FC4_TYPE); +		templen = sizeof(fcs_port_attr.port_act_fc4_type); +		memcpy(attr->value, fcs_port_attr.port_act_fc4_type, +				templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				 sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_STATE); +		templen = sizeof(fcs_port_attr.port_state); +		memcpy(attr->value, &fcs_port_attr.port_state, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen; +		++count; +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				 sizeof(templen)); + +		attr = (struct fdmi_attr_s *) curr_ptr; +		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_NUM_RPRT); +		templen = sizeof(fcs_port_attr.num_ports); +		memcpy(attr->value, &fcs_port_attr.num_ports, templen); +		templen = fc_roundup(templen, sizeof(u32)); +		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; +		len += templen;  		++count; -		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + -				sizeof(attr->len)); +		attr->len = cpu_to_be16(templen + sizeof(attr->type) + +				sizeof(templen));  	}  	/* @@ -2019,10 +2520,11 @@ bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->port_cfg.pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, -					bfa_fcs_lport_fdmi_send_rpa, fdmi); +				bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);  		return;  	}  	fdmi->fcxp = fcxp; @@ -2103,12 +2605,13 @@ bfa_fcs_lport_fdmi_timeout(void *arg)  	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);  } -void +static void  bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,  			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)  {  	struct bfa_fcs_lport_s *port = fdmi->ms->port;  	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info; +	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;  	memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s)); @@ -2144,16 +2647,28 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,  				sizeof(driver_info->host_os_patch));  	} -	hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ); +	/* Retrieve the max frame size from the port attr */ +	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); +	hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size; + +	strncpy(hba_attr->node_sym_name.symname, +		port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN); +	strcpy(hba_attr->vendor_info, "BROCADE"); +	hba_attr->num_ports = +		cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc)); +	hba_attr->fabric_name = port->fabric->lps->pr_nwwn; +	strncpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); +  } -void +static void  bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,  			  struct bfa_fcs_fdmi_port_attr_s *port_attr)  {  	struct bfa_fcs_lport_s *port = fdmi->ms->port;  	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;  	struct bfa_port_attr_s pport_attr; +	struct bfa_lport_attr_s lport_attr;  	memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s)); @@ -2170,17 +2685,41 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,  	/*  	 * Supported Speeds  	 */ -	port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS); +	switch (pport_attr.speed_supported) { +	case BFA_PORT_SPEED_16GBPS: +		port_attr->supp_speed = +			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G); +		break; + +	case BFA_PORT_SPEED_10GBPS: +		port_attr->supp_speed = +			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G); +		break; + +	case BFA_PORT_SPEED_8GBPS: +		port_attr->supp_speed = +			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G); +		break; + +	case BFA_PORT_SPEED_4GBPS: +		port_attr->supp_speed = +			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G); +		break; + +	default: +		bfa_sm_fault(port->fcs, pport_attr.speed_supported); +	}  	/*  	 * Current Speed  	 */ -	port_attr->curr_speed = cpu_to_be32(pport_attr.speed); +	port_attr->curr_speed = cpu_to_be32( +				bfa_fcs_fdmi_convert_speed(pport_attr.speed));  	/*  	 * Max PDU Size.  	 */ -	port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ); +	port_attr->max_frm_size = cpu_to_be32(pport_attr.pport_cfg.maxfrsize);  	/*  	 * OS device Name @@ -2194,8 +2733,55 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,  	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,  		sizeof(port_attr->host_name)); +	port_attr->node_name = bfa_fcs_lport_get_nwwn(port); +	port_attr->port_name = bfa_fcs_lport_get_pwwn(port); + +	strncpy(port_attr->port_sym_name.symname, +		(char *)&bfa_fcs_lport_get_psym_name(port), BFA_SYMNAME_MAXLEN); +	bfa_fcs_lport_get_attr(port, &lport_attr); +	port_attr->port_type = cpu_to_be32(lport_attr.port_type); +	port_attr->scos = pport_attr.cos_supported; +	port_attr->port_fabric_name = port->fabric->lps->pr_nwwn; +	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->port_act_fc4_type); +	port_attr->port_state = cpu_to_be32(pport_attr.port_state); +	port_attr->num_ports = cpu_to_be32(port->num_rports);  } +/* + * Convert BFA speed to FDMI format. + */ +u32 +bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed) +{ +	u32	ret; + +	switch (pport_speed) { +	case BFA_PORT_SPEED_1GBPS: +	case BFA_PORT_SPEED_2GBPS: +		ret = pport_speed; +		break; + +	case BFA_PORT_SPEED_4GBPS: +		ret = FDMI_TRANS_SPEED_4G; +		break; + +	case BFA_PORT_SPEED_8GBPS: +		ret = FDMI_TRANS_SPEED_8G; +		break; + +	case BFA_PORT_SPEED_10GBPS: +		ret = FDMI_TRANS_SPEED_10G; +		break; + +	case BFA_PORT_SPEED_16GBPS: +		ret = FDMI_TRANS_SPEED_16G; +		break; + +	default: +		ret = FDMI_TRANS_SPEED_UNKNOWN; +	} +	return ret; +}  void  bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms) @@ -2550,17 +3136,18 @@ bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->pid); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, -					bfa_fcs_lport_ms_send_gmal, ms); +				bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);  		return;  	}  	ms->fcxp = fcxp;  	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),  			     bfa_fcs_lport_get_fcid(port), -				 bfa_lps_get_peer_nwwn(port->fabric->lps)); +				 port->fabric->lps->pr_nwwn);  	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,  			  FC_CLASS_3, len, &fchs, @@ -2750,17 +3337,18 @@ bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->pid); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, -					bfa_fcs_lport_ms_send_gfn, ms); +				bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);  		return;  	}  	ms->fcxp = fcxp;  	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),  			     bfa_fcs_lport_get_fcid(port), -				 bfa_lps_get_peer_nwwn(port->fabric->lps)); +				 port->fabric->lps->pr_nwwn);  	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,  			  FC_CLASS_3, len, &fchs, @@ -2826,20 +3414,22 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->pid); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		port->stats.ms_plogi_alloc_wait++;  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, -					bfa_fcs_lport_ms_send_plogi, ms); +				bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);  		return;  	}  	ms->fcxp = fcxp;  	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), -			     bfa_os_hton3b(FC_MGMT_SERVER), +			     bfa_hton3b(FC_MGMT_SERVER),  			     bfa_fcs_lport_get_fcid(port), 0,  			     port->port_cfg.pwwn, port->port_cfg.nwwn, -				 bfa_fcport_get_maxfrsize(port->fcs->bfa)); +			     bfa_fcport_get_maxfrsize(port->fcs->bfa), +			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));  	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,  			  FC_CLASS_3, len, &fchs, @@ -2979,6 +3569,10 @@ static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,  					    struct bfa_fcxp_s *fcxp_alloced);  static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,  					    struct bfa_fcxp_s *fcxp_alloced); +static void	bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, +					struct bfa_fcxp_s *fcxp_alloced); +static void	bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, +					struct bfa_fcxp_s *fcxp_alloced);  static void     bfa_fcs_lport_ns_timeout(void *arg);  static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,  					       struct bfa_fcxp_s *fcxp, @@ -3015,6 +3609,20 @@ static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,  						u32 rsp_len,  						u32 resid_len,  						struct fchs_s *rsp_fchs); +static void     bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, +						struct bfa_fcxp_s *fcxp, +						void *cbarg, +						bfa_status_t req_status, +						u32 rsp_len, +						u32 resid_len, +						struct fchs_s *rsp_fchs); +static void     bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, +						struct bfa_fcxp_s *fcxp, +						void *cbarg, +						bfa_status_t req_status, +						u32 rsp_len, +						u32 resid_len, +						struct fchs_s *rsp_fchs);  static void     bfa_fcs_lport_ns_process_gidft_pids(  				struct bfa_fcs_lport_s *port,  				u32 *pid_buf, u32 n_pids); @@ -3039,6 +3647,8 @@ enum vport_ns_event {  	NSSM_EVENT_RFTID_SENT = 9,  	NSSM_EVENT_RFFID_SENT = 10,  	NSSM_EVENT_GIDFT_SENT = 11, +	NSSM_EVENT_RNNID_SENT = 12, +	NSSM_EVENT_RSNN_NN_SENT = 13,  };  static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns, @@ -3079,6 +3689,21 @@ static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,  						enum vport_ns_event event);  static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,  					  enum vport_ns_event event); +static void     bfa_fcs_lport_ns_sm_sending_rnn_id( +					struct bfa_fcs_lport_ns_s *ns, +					enum vport_ns_event event); +static void     bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns, +					enum vport_ns_event event); +static void     bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns, +						enum vport_ns_event event); +static void     bfa_fcs_lport_ns_sm_sending_rsnn_nn( +					struct bfa_fcs_lport_ns_s *ns, +					enum vport_ns_event event); +static void     bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns, +						enum vport_ns_event event); +static void     bfa_fcs_lport_ns_sm_rsnn_nn_retry( +					struct bfa_fcs_lport_ns_s *ns, +					enum vport_ns_event event);  /*   *	Start in offline state - awaiting linkup   */ @@ -3146,8 +3771,9 @@ bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,  		break;  	case NSSM_EVENT_RSP_OK: -		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id); -		bfa_fcs_lport_ns_send_rspn_id(ns, NULL); +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id); +		ns->num_rnnid_retries = 0; +		bfa_fcs_lport_ns_send_rnn_id(ns, NULL);  		break;  	case NSSM_EVENT_PORT_OFFLINE: @@ -3187,6 +3813,176 @@ bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,  }  static void +bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns, +					enum vport_ns_event event) +{ +	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); +	bfa_trc(ns->port->fcs, event); + +	switch (event) { +	case NSSM_EVENT_RNNID_SENT: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id); +		break; + +	case NSSM_EVENT_PORT_OFFLINE: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); +		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), +						&ns->fcxp_wqe); +		break; +	default: +		bfa_sm_fault(ns->port->fcs, event); +	} +} + +static void +bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns, +				enum vport_ns_event event) +{ +	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); +	bfa_trc(ns->port->fcs, event); + +	switch (event) { +	case NSSM_EVENT_RSP_OK: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn); +		ns->num_rnnid_retries = 0; +		ns->num_rsnn_nn_retries = 0; +		bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL); +		break; + +	case NSSM_EVENT_RSP_ERROR: +		if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) { +			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry); +			ns->port->stats.ns_retries++; +			ns->num_rnnid_retries++; +			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), +				&ns->timer, bfa_fcs_lport_ns_timeout, ns, +				BFA_FCS_RETRY_TIMEOUT); +		} else { +			bfa_sm_set_state(ns, +				bfa_fcs_lport_ns_sm_sending_rspn_id); +			bfa_fcs_lport_ns_send_rspn_id(ns, NULL); +		} +		break; + +	case NSSM_EVENT_PORT_OFFLINE: +		bfa_fcxp_discard(ns->fcxp); +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); +		break; + +	default: +		bfa_sm_fault(ns->port->fcs, event); +	} +} + +static void +bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns, +				enum vport_ns_event event) +{ +	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); +	bfa_trc(ns->port->fcs, event); + +	switch (event) { +	case NSSM_EVENT_TIMEOUT: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id); +		bfa_fcs_lport_ns_send_rnn_id(ns, NULL); +		break; + +	case NSSM_EVENT_PORT_OFFLINE: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); +		bfa_timer_stop(&ns->timer); +		break; + +	default: +		bfa_sm_fault(ns->port->fcs, event); +	} +} + +static void +bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns, +					enum vport_ns_event event) +{ +	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); +	bfa_trc(ns->port->fcs, event); + +	switch (event) { +	case NSSM_EVENT_RSNN_NN_SENT: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn); +		break; + +	case NSSM_EVENT_PORT_OFFLINE: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); +		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), +			&ns->fcxp_wqe); +		break; + +	default: +		bfa_sm_fault(ns->port->fcs, event); +	} +} + +static void +bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns, +				enum vport_ns_event event) +{ +	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); +	bfa_trc(ns->port->fcs, event); + +	switch (event) { +	case NSSM_EVENT_RSP_OK: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id); +		ns->num_rsnn_nn_retries = 0; +		bfa_fcs_lport_ns_send_rspn_id(ns, NULL); +		break; + +	case NSSM_EVENT_RSP_ERROR: +		if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) { +			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry); +			ns->port->stats.ns_retries++; +			ns->num_rsnn_nn_retries++; +			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), +					&ns->timer, bfa_fcs_lport_ns_timeout, +					ns, BFA_FCS_RETRY_TIMEOUT); +		} else { +			bfa_sm_set_state(ns, +				bfa_fcs_lport_ns_sm_sending_rspn_id); +			bfa_fcs_lport_ns_send_rspn_id(ns, NULL); +		} +		break; + +	case NSSM_EVENT_PORT_OFFLINE: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); +		bfa_fcxp_discard(ns->fcxp); +		break; + +	default: +		bfa_sm_fault(ns->port->fcs, event); +	} +} + +static void +bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns, +					enum vport_ns_event event) +{ +	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); +	bfa_trc(ns->port->fcs, event); + +	switch (event) { +	case NSSM_EVENT_TIMEOUT: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn); +		bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL); +		break; + +	case NSSM_EVENT_PORT_OFFLINE: +		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline); +		bfa_timer_stop(&ns->timer); +		break; + +	default: +		bfa_sm_fault(ns->port->fcs, event); +	} +} + +static void  bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,  				   enum vport_ns_event event)  { @@ -3583,20 +4379,22 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->pid); -fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		port->stats.ns_plogi_alloc_wait++;  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, -					bfa_fcs_lport_ns_send_plogi, ns); +				bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);  		return;  	}  	ns->fcxp = fcxp;  	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), -			     bfa_os_hton3b(FC_NAME_SERVER), +			     bfa_hton3b(FC_NAME_SERVER),  			     bfa_fcs_lport_get_fcid(port), 0,  			     port->port_cfg.pwwn, port->port_cfg.nwwn, -				 bfa_fcport_get_maxfrsize(port->fcs->bfa)); +			     bfa_fcport_get_maxfrsize(port->fcs->bfa), +			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));  	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,  			  FC_CLASS_3, len, &fchs, @@ -3665,6 +4463,162 @@ bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,  }  /* + * Register node name for port_id + */ +static void +bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) +{ +	struct bfa_fcs_lport_ns_s *ns = ns_cbarg; +	struct bfa_fcs_lport_s *port = ns->port; +	struct fchs_s  fchs; +	int	len; +	struct bfa_fcxp_s *fcxp; + +	bfa_trc(port->fcs, port->port_cfg.pwwn); + +	fcxp = fcxp_alloced ? fcxp_alloced : +			bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); +	if (!fcxp) { +		port->stats.ns_rnnid_alloc_wait++; +		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, +				bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE); +		return; +	} + +	ns->fcxp = fcxp; + +	len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), +				bfa_fcs_lport_get_fcid(port), +				bfa_fcs_lport_get_fcid(port), +				bfa_fcs_lport_get_nwwn(port)); + +	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, +			  FC_CLASS_3, len, &fchs, +			  bfa_fcs_lport_ns_rnn_id_response, (void *)ns, +			  FC_MAX_PDUSZ, FC_FCCT_TOV); + +	port->stats.ns_rnnid_sent++; +	bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT); +} + +static void +bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, +				void *cbarg, bfa_status_t req_status, +				u32 rsp_len, u32 resid_len, +				struct fchs_s *rsp_fchs) + +{ +	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; +	struct bfa_fcs_lport_s *port = ns->port; +	struct ct_hdr_s	*cthdr = NULL; + +	bfa_trc(port->fcs, port->port_cfg.pwwn); + +	/* +	 * Sanity Checks +	 */ +	if (req_status != BFA_STATUS_OK) { +		bfa_trc(port->fcs, req_status); +		port->stats.ns_rnnid_rsp_err++; +		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); +		return; +	} + +	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); +	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); + +	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { +		port->stats.ns_rnnid_accepts++; +		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); +		return; +	} + +	port->stats.ns_rnnid_rejects++; +	bfa_trc(port->fcs, cthdr->reason_code); +	bfa_trc(port->fcs, cthdr->exp_code); +	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); +} + +/* + * Register the symbolic node name for a given node name. + */ +static void +bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) +{ +	struct bfa_fcs_lport_ns_s *ns = ns_cbarg; +	struct bfa_fcs_lport_s *port = ns->port; +	struct fchs_s  fchs; +	int     len; +	struct bfa_fcxp_s *fcxp; +	u8 *nsymbl; + +	bfa_trc(port->fcs, port->port_cfg.pwwn); + +	fcxp = fcxp_alloced ? fcxp_alloced : +			bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE); +	if (!fcxp) { +		port->stats.ns_rsnn_nn_alloc_wait++; +		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, +				bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE); +		return; +	} +	ns->fcxp = fcxp; + +	nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name( +					bfa_fcs_get_base_port(port->fcs))); + +	len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), +				bfa_fcs_lport_get_fcid(port), +				bfa_fcs_lport_get_nwwn(port), nsymbl); + +	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, +			  FC_CLASS_3, len, &fchs, +			  bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns, +			  FC_MAX_PDUSZ, FC_FCCT_TOV); + +	port->stats.ns_rsnn_nn_sent++; + +	bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT); +} + +static void +bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, +				void *cbarg, bfa_status_t req_status, +				u32 rsp_len, u32 resid_len, +				struct fchs_s *rsp_fchs) +{ +	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg; +	struct bfa_fcs_lport_s *port = ns->port; +	struct ct_hdr_s	*cthdr = NULL; + +	bfa_trc(port->fcs, port->port_cfg.pwwn); + +	/* +	 * Sanity Checks +	 */ +	if (req_status != BFA_STATUS_OK) { +		bfa_trc(port->fcs, req_status); +		port->stats.ns_rsnn_nn_rsp_err++; +		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); +		return; +	} + +	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); +	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code); + +	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { +		port->stats.ns_rsnn_nn_accepts++; +		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); +		return; +	} + +	port->stats.ns_rsnn_nn_rejects++; +	bfa_trc(port->fcs, cthdr->reason_code); +	bfa_trc(port->fcs, cthdr->exp_code); +	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); +} + +/*   * Register the symbolic port name.   */  static void @@ -3682,11 +4636,12 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->port_cfg.pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		port->stats.ns_rspnid_alloc_wait++;  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, -					bfa_fcs_lport_ns_send_rspn_id, ns); +				bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);  		return;  	}  	ns->fcxp = fcxp; @@ -3783,11 +4738,12 @@ bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->port_cfg.pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		port->stats.ns_rftid_alloc_wait++;  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, -					bfa_fcs_lport_ns_send_rft_id, ns); +				bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);  		return;  	}  	ns->fcxp = fcxp; @@ -3856,11 +4812,12 @@ bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->port_cfg.pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		port->stats.ns_rffid_alloc_wait++;  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, -					bfa_fcs_lport_ns_send_rff_id, ns); +				bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);  		return;  	}  	ns->fcxp = fcxp; @@ -3939,11 +4896,12 @@ bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->pid); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		port->stats.ns_gidft_alloc_wait++;  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, -					bfa_fcs_lport_ns_send_gid_ft, ns); +				bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);  		return;  	}  	ns->fcxp = fcxp; @@ -4073,6 +5031,10 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,  	struct fcgs_gidft_resp_s *gidft_entry;  	struct bfa_fcs_rport_s *rport;  	u32        ii; +	struct bfa_fcs_fabric_s *fabric = port->fabric; +	struct bfa_fcs_vport_s *vport; +	struct list_head *qe; +	u8 found = 0;  	for (ii = 0; ii < n_pids; ii++) {  		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii]; @@ -4081,6 +5043,29 @@ bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,  			continue;  		/* +		 * Ignore PID if it is of base port +		 * (Avoid vports discovering base port as remote port) +		 */ +		if (gidft_entry->pid == fabric->bport.pid) +			continue; + +		/* +		 * Ignore PID if it is of vport created on the same base port +		 * (Avoid vport discovering every other vport created on the +		 * same port as remote port) +		 */ +		list_for_each(qe, &fabric->vport_q) { +			vport = (struct bfa_fcs_vport_s *) qe; +			if (vport->lport.pid == gidft_entry->pid) +				found = 1; +		} + +		if (found) { +			found = 0; +			continue; +		} + +		/*  		 * Check if this rport already exists  		 */  		rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid); @@ -4147,10 +5132,11 @@ bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)  	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);  	bfa_trc(port->fcs, port->pid); -	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY); +	if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online)) +		bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);  } -void +static void  bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)  { @@ -4163,10 +5149,71 @@ bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)  	for (ii = 0 ; ii < nwwns; ++ii) {  		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]); -		bfa_assert(rport); +		WARN_ON(!rport);  	}  } +void +bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) +{ +	struct bfa_fcs_lport_ns_s *ns = cbarg; +	struct bfa_fcs_lport_s *port = ns->port; +	struct fchs_s fchs; +	struct bfa_fcxp_s *fcxp; +	u8 symbl[256]; +	u8 *psymbl = &symbl[0]; +	int len; + +	/* Avoid sending RSPN in the following states. */ +	if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) || +	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) || +	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) || +	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) || +	    bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry)) +		return; + +	memset(symbl, 0, sizeof(symbl)); +	bfa_trc(port->fcs, port->port_cfg.pwwn); + +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE); +	if (!fcxp) { +		port->stats.ns_rspnid_alloc_wait++; +		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, +			bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE); +		return; +	} + +	ns->fcxp = fcxp; + +	if (port->vport) { +		/* +		 * For Vports, we append the vport's port symbolic name +		 * to that of the base port. +		 */ +		strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name +			(bfa_fcs_get_base_port(port->fcs))), +			strlen((char *)&bfa_fcs_lport_get_psym_name( +			bfa_fcs_get_base_port(port->fcs)))); + +		/* Ensure we have a null terminating string. */ +		((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name( +		 bfa_fcs_get_base_port(port->fcs)))] = 0; + +		strncat((char *)psymbl, +			(char *)&(bfa_fcs_lport_get_psym_name(port)), +			strlen((char *)&bfa_fcs_lport_get_psym_name(port))); +	} + +	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), +			      bfa_fcs_lport_get_fcid(port), 0, psymbl); + +	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, +		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); + +	port->stats.ns_rspnid_sent++; +} +  /*   * FCS SCN   */ @@ -4341,10 +5388,11 @@ bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(port->fcs, port->pid);  	bfa_trc(port->fcs, port->port_cfg.pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe, -					bfa_fcs_lport_scn_send_scr, scn); +				bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);  		return;  	}  	scn->fcxp = fcxp; @@ -4352,8 +5400,8 @@ bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	/* Handle VU registrations for Base port only */  	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {  		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), -				bfa_lps_is_brcd_fabric(port->fabric->lps), -							port->pid, 0); +				port->fabric->lps->brcd_switch, +				port->pid, 0);  	} else {  	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),  				    BFA_FALSE, @@ -4426,7 +5474,7 @@ bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,  	bfa_trc(port->fcs, rx_fchs->s_id); -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -4488,7 +5536,7 @@ bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)  }  void -bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port) +bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)  {  	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); @@ -4500,14 +5548,33 @@ static void  bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)  {  	struct bfa_fcs_rport_s *rport; +	struct bfa_fcs_fabric_s *fabric = port->fabric; +	struct bfa_fcs_vport_s *vport; +	struct list_head *qe;  	bfa_trc(port->fcs, rpid);  	/* +	 * Ignore PID if it is of base port or of vports created on the +	 * same base port. It is to avoid vports discovering base port or +	 * other vports created on same base port as remote port +	 */ +	if (rpid == fabric->bport.pid) +		return; + +	list_for_each(qe, &fabric->vport_q) { +		vport = (struct bfa_fcs_vport_s *) qe; +		if (vport->lport.pid == rpid) +			return; +	} +	/*  	 * If this is an unknown device, then it just came online.  	 * Otherwise let rport handle the RSCN event.  	 */  	rport = bfa_fcs_lport_get_rport_by_pid(port, rpid); +	if (!rport) +		rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid); +  	if (rport == NULL) {  		/*  		 * If min cfg mode is enabled, we donot need to @@ -4626,7 +5693,7 @@ bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,  		default: -			bfa_assert(0); +			WARN_ON(1);  			nsquery = BFA_TRUE;  		}  	} @@ -4672,7 +5739,7 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,  	while ((qe != qh) && (i < nrports)) {  		rport = (struct bfa_fcs_rport_s *) qe; -		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { +		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {  			qe = bfa_q_next(qe);  			bfa_trc(fcs, (u32) rport->pwwn);  			bfa_trc(fcs, rport->pid); @@ -4700,15 +5767,15 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,  }  void -bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, -	 wwn_t rport_wwns[], int *nrports) +bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port, +		struct bfa_rport_qualifier_s rports[], int *nrports)  {  	struct list_head	*qh, *qe;  	struct bfa_fcs_rport_s *rport = NULL;  	int	i;  	struct bfa_fcs_s	*fcs; -	if (port == NULL || rport_wwns == NULL || *nrports == 0) +	if (port == NULL || rports == NULL || *nrports == 0)  		return;  	fcs = port->fcs; @@ -4720,7 +5787,7 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,  	while ((qe != qh) && (i < *nrports)) {  		rport = (struct bfa_fcs_rport_s *) qe; -		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { +		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {  			qe = bfa_q_next(qe);  			bfa_trc(fcs, (u32) rport->pwwn);  			bfa_trc(fcs, rport->pid); @@ -4728,7 +5795,13 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,  			continue;  		} -		rport_wwns[i] = rport->pwwn; +		if (!rport->pwwn && !rport->pid) { +			qe = bfa_q_next(qe); +			continue; +		} + +		rports[i].pwwn = rport->pwwn; +		rports[i].pid = rport->pid;  		i++;  		qe = bfa_q_next(qe); @@ -4771,9 +5844,9 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)  	while (qe != qh) {  		rport = (struct bfa_fcs_rport_s *) qe; -		if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) || -			(bfa_fcs_rport_get_state(rport) == -			  BFA_RPORT_OFFLINE)) { +		if ((bfa_ntoh3b(rport->pid) > 0xFFF000) || +			(bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) || +			(rport->scsi_function != BFA_RPORT_TARGET)) {  			qe = bfa_q_next(qe);  			continue;  		} @@ -4786,17 +5859,15 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)  				bfa_fcport_get_ratelim_speed(port->fcs->bfa);  		} -		if	((rport_speed  == BFA_PORT_SPEED_8GBPS) || -			(rport_speed > port_speed)) { -			max_speed = rport_speed; -			break; -		} else if (rport_speed > max_speed) { +		if (rport_speed > max_speed)  			max_speed = rport_speed; -		}  		qe = bfa_q_next(qe);  	} +	if (max_speed > port_speed) +		max_speed = port_speed; +  	bfa_trc(fcs, max_speed);  	return max_speed;  } @@ -4807,7 +5878,7 @@ bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)  	struct bfa_fcs_vport_s *vport;  	bfa_fcs_vf_t   *vf; -	bfa_assert(fcs != NULL); +	WARN_ON(fcs == NULL);  	vf = bfa_fcs_vf_lookup(fcs, vf_id);  	if (vf == NULL) { @@ -4853,7 +5924,7 @@ bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,  		port_info->max_vports_supp =  			bfa_lps_get_max_vport(port->fcs->bfa);  		port_info->num_vports_inuse = -			bfa_fcs_fabric_vport_count(port->fabric); +			port->fabric->num_vports;  		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;  		port_info->num_rports_inuse = port->num_rports;  	} else { @@ -4887,6 +5958,15 @@ bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)  }  /* + * Let new loop map create missing rports + */ +void +bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port) +{ +	bfa_fcs_lport_loop_online(port); +} + +/*   * FCS virtual port state machine   */ @@ -4928,6 +6008,8 @@ enum bfa_fcs_vport_event {  	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */  	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/  	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */ +	BFA_FCS_VPORT_SM_STOPCOMP = 14,	/* vport delete completion */ +	BFA_FCS_VPORT_SM_FABRIC_MAX = 15, /* max vports on fabric */  };  static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, @@ -4940,6 +6022,8 @@ static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,  				       enum bfa_fcs_vport_event event);  static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,  					     enum bfa_fcs_vport_event event); +static void	bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, +					enum bfa_fcs_vport_event event);  static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,  					enum bfa_fcs_vport_event event);  static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, @@ -4950,6 +6034,10 @@ static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,  				      enum bfa_fcs_vport_event event);  static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,  				      enum bfa_fcs_vport_event event); +static void	bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport, +					enum bfa_fcs_vport_event event); +static void	bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport, +					enum bfa_fcs_vport_event event);  static struct bfa_sm_table_s  vport_sm_table[] = {  	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT}, @@ -4957,6 +6045,7 @@ static struct bfa_sm_table_s  vport_sm_table[] = {  	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},  	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},  	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY}, +	{BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},  	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},  	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},  	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP}, @@ -4997,7 +6086,8 @@ bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,  	switch (event) {  	case BFA_FCS_VPORT_SM_START: -		if (bfa_fcs_fabric_is_online(__vport_fabric(vport)) +		if (bfa_sm_cmp_state(__vport_fabric(vport), +					bfa_fcs_fabric_sm_online)  		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {  			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);  			bfa_fcs_vport_do_fdisc(vport); @@ -5051,6 +6141,11 @@ bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,  		bfa_fcs_vport_do_fdisc(vport);  		break; +	case BFA_FCS_VPORT_SM_STOP: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); +		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP); +		break; +  	case BFA_FCS_VPORT_SM_OFFLINE:  		/*  		 * This can happen if the vport couldn't be initialzied @@ -5079,14 +6174,12 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,  	switch (event) {  	case BFA_FCS_VPORT_SM_DELETE: -		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); -		bfa_lps_discard(vport->lps); -		bfa_fcs_lport_delete(&vport->lport); +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);  		break;  	case BFA_FCS_VPORT_SM_OFFLINE:  		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); -		bfa_lps_discard(vport->lps); +		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);  		break;  	case BFA_FCS_VPORT_SM_RSP_OK: @@ -5102,6 +6195,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,  		break;  	case BFA_FCS_VPORT_SM_RSP_FAILED: +	case BFA_FCS_VPORT_SM_FABRIC_MAX:  		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);  		break; @@ -5149,6 +6243,42 @@ bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,  }  /* + * FDISC is in progress and we got a vport delete request - + * this is a wait state while we wait for fdisc response and + * we will transition to the appropriate state - on rsp status. + */ +static void +bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport, +				enum bfa_fcs_vport_event event) +{ +	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); +	bfa_trc(__vport_fcs(vport), event); + +	switch (event) { +	case BFA_FCS_VPORT_SM_RSP_OK: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); +		bfa_fcs_lport_delete(&vport->lport); +		break; + +	case BFA_FCS_VPORT_SM_DELETE: +		break; + +	case BFA_FCS_VPORT_SM_OFFLINE: +	case BFA_FCS_VPORT_SM_RSP_ERROR: +	case BFA_FCS_VPORT_SM_RSP_FAILED: +	case BFA_FCS_VPORT_SM_FABRIC_MAX: +	case BFA_FCS_VPORT_SM_RSP_DUP_WWN: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); +		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); +		bfa_fcs_lport_delete(&vport->lport); +		break; + +	default: +		bfa_sm_fault(__vport_fcs(vport), event); +	} +} + +/*   * Vport is online (FDISC is complete).   */  static void @@ -5164,9 +6294,14 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,  		bfa_fcs_lport_delete(&vport->lport);  		break; +	case BFA_FCS_VPORT_SM_STOP: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping); +		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP); +		break; +  	case BFA_FCS_VPORT_SM_OFFLINE:  		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); -		bfa_lps_discard(vport->lps); +		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);  		bfa_fcs_lport_offline(&vport->lport);  		break; @@ -5176,6 +6311,32 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,  }  /* + * Vport is being stopped - awaiting lport stop completion to send + * LOGO to fabric. + */ +static void +bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport, +			  enum bfa_fcs_vport_event event) +{ +	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); +	bfa_trc(__vport_fcs(vport), event); + +	switch (event) { +	case BFA_FCS_VPORT_SM_STOPCOMP: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop); +		bfa_fcs_vport_do_logo(vport); +		break; + +	case BFA_FCS_VPORT_SM_OFFLINE: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); +		break; + +	default: +		bfa_sm_fault(__vport_fcs(vport), event); +	} +} + +/*   * Vport is being deleted - awaiting lport delete completion to send   * LOGO to fabric.   */ @@ -5245,6 +6406,10 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,  		bfa_fcs_vport_free(vport);  		break; +	case BFA_FCS_VPORT_SM_STOPCOMP: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); +		break; +  	case BFA_FCS_VPORT_SM_DELETE:  		break; @@ -5254,6 +6419,34 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,  }  /* + * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup + * is done. + */ +static void +bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport, +			       enum bfa_fcs_vport_event event) +{ +	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); +	bfa_trc(__vport_fcs(vport), event); + +	switch (event) { +	case BFA_FCS_VPORT_SM_OFFLINE: +		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); +		/* +		 * !!! fall through !!! +		 */ + +	case BFA_FCS_VPORT_SM_RSP_OK: +	case BFA_FCS_VPORT_SM_RSP_ERROR: +		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); +		break; + +	default: +		bfa_sm_fault(__vport_fcs(vport), event); +	} +} + +/*   * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup   * is done.   */ @@ -5266,7 +6459,7 @@ bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,  	switch (event) {  	case BFA_FCS_VPORT_SM_OFFLINE: -		bfa_lps_discard(vport->lps); +		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);  		/*  		 * !!! fall through !!!  		 */ @@ -5291,6 +6484,31 @@ bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,   *  fcs_vport_private FCS virtual port private functions   */  /* + * Send AEN notification + */ +static void +bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port, +		       enum bfa_lport_aen_event event) +{ +	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad; +	struct bfa_aen_entry_s  *aen_entry; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	aen_entry->aen_data.lport.vf_id = port->fabric->vf_id; +	aen_entry->aen_data.lport.roles = port->port_cfg.roles; +	aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn( +					bfa_fcs_get_base_port(port->fcs)); +	aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port); + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq, +				  BFA_AEN_CAT_LPORT, event); +} + +/*   * This routine will be called to send a FDISC command.   */  static void @@ -5305,20 +6523,23 @@ bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)  static void  bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)  { -	u8		lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps); -	u8		lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps); +	u8		lsrjt_rsn = vport->lps->lsrjt_rsn; +	u8		lsrjt_expl = vport->lps->lsrjt_expl;  	bfa_trc(__vport_fcs(vport), lsrjt_rsn);  	bfa_trc(__vport_fcs(vport), lsrjt_expl);  	/* For certain reason codes, we don't want to retry. */ -	switch (bfa_lps_get_lsrjt_expl(vport->lps)) { +	switch (vport->lps->lsrjt_expl) {  	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */  	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */  		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)  			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); -		else +		else { +			bfa_fcs_vport_aen_post(&vport->lport, +					BFA_LPORT_AEN_NPIV_DUP_WWN);  			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); +		}  		break;  	case FC_LS_RJT_EXP_INSUFF_RES: @@ -5328,11 +6549,17 @@ bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)  		 */  		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)  			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); -		else -			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); +		else { +			bfa_fcs_vport_aen_post(&vport->lport, +					BFA_LPORT_AEN_NPIV_FABRIC_MAX); +			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_FABRIC_MAX); +		}  		break;  	default: +		if (vport->fdisc_retries == 0) +			bfa_fcs_vport_aen_post(&vport->lport, +					BFA_LPORT_AEN_NPIV_UNKNOWN);  		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);  	}  } @@ -5380,15 +6607,21 @@ bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)  			(struct bfad_vport_s *)vport->vport_drv;  	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport); +	bfa_lps_delete(vport->lps); -	if (vport_drv->comp_del) +	if (vport_drv->comp_del) {  		complete(vport_drv->comp_del); +		return; +	} -	bfa_lps_delete(vport->lps); +	/* +	 * We queue the vport delete work to the IM work_q from here. +	 * The memory for the bfad_vport_s is freed from the FC function +	 * template vport_delete entry point. +	 */ +	bfad_im_port_delete(vport_drv->drv_port.bfad, &vport_drv->drv_port);  } - -  /*   *  fcs_vport_public FCS virtual port public interfaces   */ @@ -5400,7 +6633,10 @@ void  bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)  {  	vport->vport_stats.fab_online++; -	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); +	if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) +		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); +	else +		vport->vport_stats.fab_no_npiv++;  }  /* @@ -5421,6 +6657,16 @@ bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)  {  	vport->vport_stats.fab_cleanup++;  } + +/* + * Stop notification from fabric SM. To be invoked from within FCS. + */ +void +bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport) +{ +	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); +} +  /*   * delete notification from fabric SM. To be invoked from within FCS.   */ @@ -5431,6 +6677,15 @@ bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)  }  /* + * Stop completion callback from associated lport + */ +void +bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport) +{ +	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP); +} + +/*   * Delete completion callback from associated lport   */  void @@ -5476,7 +6731,7 @@ bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,  	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)  		return BFA_STATUS_VPORT_EXISTS; -	if (bfa_fcs_fabric_vport_count(&fcs->fabric) == +	if (fcs->fabric.num_vports ==  			bfa_lps_get_max_vport(fcs->bfa))  		return BFA_STATUS_VPORT_MAX; @@ -5618,33 +6873,6 @@ bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,  	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);  } -/* - *	Use this function to get vport's statistics. - * - *	param[in]	vport	pointer to bfa_fcs_vport_t. - *	param[out]	stats	pointer to return vport statistics in - * - *	return None - */ -void -bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, -			struct bfa_vport_stats_s *stats) -{ -	*stats = vport->vport_stats; -} - -/* - *	Use this function to clear vport's statistics. - * - *	param[in]	vport	pointer to bfa_fcs_vport_t. - * - *	return None - */ -void -bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport) -{ -	memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s)); -}  /*   *	Lookup a virtual port. Excludes base port from lookup. @@ -5682,9 +6910,9 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)  	switch (status) {  	case BFA_STATUS_OK:  		/* -		 * Initialiaze the V-Port fields +		 * Initialize the V-Port fields  		 */ -		__vport_fcid(vport) = bfa_lps_get_pid(vport->lps); +		__vport_fcid(vport) = vport->lps->lp_pid;  		vport->vport_stats.fdisc_accepts++;  		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);  		break; @@ -5697,7 +6925,7 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)  		break;  	case BFA_STATUS_EPROTOCOL: -		switch (bfa_lps_get_extstatus(vport->lps)) { +		switch (vport->lps->ext_status) {  		case BFA_EPROTO_BAD_ACCEPT:  			vport->vport_stats.fdisc_acc_bad++;  			break; @@ -5710,7 +6938,19 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)  			break;  		} -		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); +		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) +			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); +		else +			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); + +		break; + +	case BFA_STATUS_ETIMER: +		vport->vport_stats.fdisc_timeouts++; +		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) +			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); +		else +			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);  		break;  	case BFA_STATUS_FABRIC_RJT: diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 47f35c0ef29..2035b0d6435 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -19,9 +19,10 @@   *  rport.c Remote port implementation.   */ +#include "bfad_drv.h" +#include "bfad_im.h"  #include "bfa_fcs.h"  #include "bfa_fcbuild.h" -#include "bfad_drv.h"  BFA_TRC_FILE(FCS, RPORT); @@ -29,14 +30,22 @@ static u32  bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;  	 /* In millisecs */  /* + * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports + * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports + */ +static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS; + +/*   * forward declarations   */  static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(  		struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);  static void	bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);  static void	bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport); -static void	bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport); -static void	bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport); +static void	bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport); +static void	bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport); +static void	bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport); +static void	bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);  static void	bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,  					struct fc_logi_s *plogi);  static void	bfa_fcs_rport_timeout(void *arg); @@ -75,30 +84,7 @@ static void	bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,  static void	bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,  				struct fchs_s *rx_fchs, u16 len);  static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport); -/* - *  fcs_rport_sm FCS rport state machine events - */ - -enum rport_event { -	RPSM_EVENT_PLOGI_SEND	= 1,	/*  new rport; start with PLOGI */ -	RPSM_EVENT_PLOGI_RCVD	= 2,	/*  Inbound PLOGI from remote port */ -	RPSM_EVENT_PLOGI_COMP	= 3,	/*  PLOGI completed to rport	*/ -	RPSM_EVENT_LOGO_RCVD	= 4,	/*  LOGO from remote device	*/ -	RPSM_EVENT_LOGO_IMP	= 5,	/*  implicit logo for SLER	*/ -	RPSM_EVENT_FCXP_SENT	= 6,	/*  Frame from has been sent	*/ -	RPSM_EVENT_DELETE	= 7,	/*  RPORT delete request	*/ -	RPSM_EVENT_SCN		= 8,	/*  state change notification	*/ -	RPSM_EVENT_ACCEPTED	= 9,	/*  Good response from remote device */ -	RPSM_EVENT_FAILED	= 10,	/*  Request to rport failed.	*/ -	RPSM_EVENT_TIMEOUT	= 11,	/*  Rport SM timeout event	*/ -	RPSM_EVENT_HCB_ONLINE  = 12,	/*  BFA rport online callback	*/ -	RPSM_EVENT_HCB_OFFLINE = 13,	/*  BFA rport offline callback	*/ -	RPSM_EVENT_FC4_OFFLINE = 14,	/*  FC-4 offline complete	*/ -	RPSM_EVENT_ADDRESS_CHANGE = 15,	/*  Rport's PID has changed	*/ -	RPSM_EVENT_ADDRESS_DISC = 16,	/*  Need to Discover rport's PID */ -	RPSM_EVENT_PRLO_RCVD   = 17,	/*  PRLO from remote device	*/ -	RPSM_EVENT_PLOGI_RETRY = 18,	/*  Retry PLOGI continously */ -}; +static void	bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);  static void	bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,  					enum rport_event event); @@ -110,6 +96,8 @@ static void	bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,  						enum rport_event event);  static void	bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,  					enum rport_event event); +static void	bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport, +					enum rport_event event);  static void	bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,  						enum rport_event event);  static void	bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, @@ -118,9 +106,13 @@ static void	bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,  						 enum rport_event event);  static void	bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,  					 enum rport_event event); -static void	bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, -						enum rport_event event); -static void	bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, +static void	bfa_fcs_rport_sm_adisc_online_sending( +			struct bfa_fcs_rport_s *rport, enum rport_event event); +static void	bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport, +					enum rport_event event); +static void	bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s +					*rport, enum rport_event event); +static void	bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,  					enum rport_event event);  static void	bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,  						enum rport_event event); @@ -146,6 +138,10 @@ static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,  						enum rport_event event);  static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,  						enum rport_event event); +static void	bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport, +						enum rport_event event); +static void	bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport, +						enum rport_event event);  static struct bfa_sm_table_s rport_sm_table[] = {  	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT}, @@ -153,12 +149,15 @@ static struct bfa_sm_table_s rport_sm_table[] = {  	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},  	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},  	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI}, +	{BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},  	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},  	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},  	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},  	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY}, -	{BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC}, -	{BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC}, +	{BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC}, +	{BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC}, +	{BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC}, +	{BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},  	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},  	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},  	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE}, @@ -238,10 +237,19 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,  		bfa_fcs_rport_send_plogiacc(rport, NULL);  		break; +	case RPSM_EVENT_SCN_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); +		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); +		bfa_timer_start(rport->fcs->bfa, &rport->timer, +				bfa_fcs_rport_timeout, rport, +				bfa_fcs_rport_del_timeout); +		break;  	case RPSM_EVENT_ADDRESS_CHANGE: -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		/* query the NS */  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); +		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) != +					BFA_PORT_TOPOLOGY_LOOP));  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);  		rport->ns_retries = 0;  		bfa_fcs_rport_send_nsdisc(rport, NULL); @@ -275,8 +283,8 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,  	switch (event) {  	case RPSM_EVENT_FCXP_SENT: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); -		bfa_fcs_rport_hal_online(rport); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online); +		bfa_fcs_rport_fcs_online_action(rport);  		break;  	case RPSM_EVENT_DELETE: @@ -286,12 +294,21 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,  		break;  	case RPSM_EVENT_PLOGI_RCVD: -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_PLOGI_COMP: +	case RPSM_EVENT_FAB_SCN:  		/*  		 * Ignore, SCN is possibly online notification.  		 */  		break; +	case RPSM_EVENT_SCN_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); +		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); +		bfa_timer_start(rport->fcs->bfa, &rport->timer, +				bfa_fcs_rport_timeout, rport, +				bfa_fcs_rport_del_timeout); +		break; +  	case RPSM_EVENT_ADDRESS_CHANGE:  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); @@ -352,9 +369,19 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,  		bfa_fcs_rport_send_plogiacc(rport, NULL);  		break; +	case RPSM_EVENT_SCN_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); +		bfa_timer_stop(&rport->timer); +		bfa_timer_start(rport->fcs->bfa, &rport->timer, +				bfa_fcs_rport_timeout, rport, +				bfa_fcs_rport_del_timeout); +		break; +  	case RPSM_EVENT_ADDRESS_CHANGE: -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		bfa_timer_stop(&rport->timer); +		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) != +					BFA_PORT_TOPOLOGY_LOOP));  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);  		rport->ns_retries = 0;  		bfa_fcs_rport_send_nsdisc(rport, NULL); @@ -370,9 +397,9 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,  		break;  	case RPSM_EVENT_PLOGI_COMP: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);  		bfa_timer_stop(&rport->timer); -		bfa_fcs_rport_hal_online(rport); +		bfa_fcs_rport_fcs_online_action(rport);  		break;  	default: @@ -392,9 +419,9 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)  	switch (event) {  	case RPSM_EVENT_ACCEPTED: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);  		rport->plogi_retries = 0; -		bfa_fcs_rport_hal_online(rport); +		bfa_fcs_rport_fcs_online_action(rport);  		break;  	case RPSM_EVENT_LOGO_RCVD: @@ -419,6 +446,7 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)  					BFA_FCS_RETRY_TIMEOUT);  		} else {  			bfa_stats(rport->port, rport_del_max_plogi_retry); +			rport->old_pid = rport->pid;  			rport->pid = 0;  			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);  			bfa_timer_start(rport->fcs->bfa, &rport->timer, @@ -427,7 +455,18 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)  		}  		break; -	case	RPSM_EVENT_PLOGI_RETRY: +	case RPSM_EVENT_SCN_ONLINE: +		break; + +	case RPSM_EVENT_SCN_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); +		bfa_fcxp_discard(rport->fcxp); +		bfa_timer_start(rport->fcs->bfa, &rport->timer, +				bfa_fcs_rport_timeout, rport, +				bfa_fcs_rport_del_timeout); +		break; + +	case RPSM_EVENT_PLOGI_RETRY:  		rport->plogi_retries = 0;  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);  		bfa_timer_start(rport->fcs->bfa, &rport->timer, @@ -445,8 +484,10 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)  		break;  	case RPSM_EVENT_ADDRESS_CHANGE: -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		bfa_fcxp_discard(rport->fcxp); +		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) != +					BFA_PORT_TOPOLOGY_LOOP));  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);  		rport->ns_retries = 0;  		bfa_fcs_rport_send_nsdisc(rport, NULL); @@ -465,13 +506,78 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)  		break;  	case RPSM_EVENT_PLOGI_COMP: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_hal_online(rport); +		bfa_fcs_rport_fcs_online_action(rport); +		break; + +	default: +		bfa_sm_fault(rport->fcs, event); +	} +} + +/* + * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function + */ +static void +bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport, +				enum rport_event event) +{ +	bfa_trc(rport->fcs, rport->pwwn); +	bfa_trc(rport->fcs, rport->pid); +	bfa_trc(rport->fcs, event); + +	switch (event) { +	case RPSM_EVENT_FC4_FCS_ONLINE: +		if (rport->scsi_function == BFA_RPORT_INITIATOR) { +			if (!BFA_FCS_PID_IS_WKA(rport->pid)) +				bfa_fcs_rpf_rport_online(rport); +			bfa_sm_set_state(rport, bfa_fcs_rport_sm_online); +			break; +		} + +		if (!rport->bfa_rport) +			rport->bfa_rport = +				bfa_rport_create(rport->fcs->bfa, rport); + +		if (rport->bfa_rport) { +			bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +			bfa_fcs_rport_hal_online(rport); +		} else { +			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); +			bfa_fcs_rport_fcs_offline_action(rport); +		} +		break; + +	case RPSM_EVENT_PLOGI_RCVD: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); +		rport->plogi_pending = BFA_TRUE; +		bfa_fcs_rport_fcs_offline_action(rport); +		break; + +	case RPSM_EVENT_PLOGI_COMP: +	case RPSM_EVENT_LOGO_IMP: +	case RPSM_EVENT_ADDRESS_CHANGE: +	case RPSM_EVENT_FAB_SCN: +	case RPSM_EVENT_SCN_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); +		bfa_fcs_rport_fcs_offline_action(rport); +		break; + +	case RPSM_EVENT_LOGO_RCVD: +	case RPSM_EVENT_PRLO_RCVD: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); +		bfa_fcs_rport_fcs_offline_action(rport); +		break; + +	case RPSM_EVENT_DELETE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); +		bfa_fcs_rport_fcs_offline_action(rport);  		break;  	default:  		bfa_sm_fault(rport->fcs, event); +		break;  	}  } @@ -490,40 +596,35 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,  	switch (event) {  	case RPSM_EVENT_HCB_ONLINE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online); -		bfa_fcs_rport_online_action(rport); +		bfa_fcs_rport_hal_online_action(rport);  		break; -	case RPSM_EVENT_PRLO_RCVD: +	case RPSM_EVENT_PLOGI_COMP:  		break; +	case RPSM_EVENT_PRLO_RCVD:  	case RPSM_EVENT_LOGO_RCVD: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); -		bfa_rport_offline(rport->bfa_rport); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); +		bfa_fcs_rport_fcs_offline_action(rport);  		break; +	case RPSM_EVENT_FAB_SCN:  	case RPSM_EVENT_LOGO_IMP:  	case RPSM_EVENT_ADDRESS_CHANGE: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); -		bfa_rport_offline(rport->bfa_rport); +	case RPSM_EVENT_SCN_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); +		bfa_fcs_rport_fcs_offline_action(rport);  		break;  	case RPSM_EVENT_PLOGI_RCVD: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); -		bfa_rport_offline(rport->bfa_rport); -		bfa_fcs_rport_send_plogiacc(rport, NULL); +		rport->plogi_pending = BFA_TRUE; +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); +		bfa_fcs_rport_fcs_offline_action(rport);  		break;  	case RPSM_EVENT_DELETE: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); -		bfa_rport_offline(rport->bfa_rport); -		break; - -	case RPSM_EVENT_SCN: -		/* -		 * @todo -		 * Ignore SCN - PLOGI just completed, FC-4 login should detect -		 * device failures. -		 */ +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); +		bfa_fcs_rport_fcs_offline_action(rport);  		break;  	default: @@ -542,14 +643,15 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)  	bfa_trc(rport->fcs, event);  	switch (event) { -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {  			bfa_sm_set_state(rport,  					 bfa_fcs_rport_sm_nsquery_sending);  			rport->ns_retries = 0;  			bfa_fcs_rport_send_nsdisc(rport, NULL);  		} else { -			bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending); +			bfa_sm_set_state(rport, +				bfa_fcs_rport_sm_adisc_online_sending);  			bfa_fcs_rport_send_adisc(rport, NULL);  		}  		break; @@ -557,21 +659,23 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)  	case RPSM_EVENT_PLOGI_RCVD:  	case RPSM_EVENT_LOGO_IMP:  	case RPSM_EVENT_ADDRESS_CHANGE: +	case RPSM_EVENT_SCN_OFFLINE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_DELETE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break; +	case RPSM_EVENT_SCN_ONLINE:  	case RPSM_EVENT_PLOGI_COMP:  		break; @@ -600,10 +704,10 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,  	case RPSM_EVENT_DELETE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		/*  		 * ignore SCN, wait for response to query itself  		 */ @@ -613,24 +717,16 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,  	case RPSM_EVENT_PRLO_RCVD:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_LOGO_IMP: -		rport->pid = 0; -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); -		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_timer_start(rport->fcs->bfa, &rport->timer, -				bfa_fcs_rport_timeout, rport, -				bfa_fcs_rport_del_timeout); -		break; -  	case RPSM_EVENT_PLOGI_RCVD:  	case RPSM_EVENT_ADDRESS_CHANGE:  	case RPSM_EVENT_PLOGI_COMP:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	default: @@ -651,7 +747,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)  	switch (event) {  	case RPSM_EVENT_ACCEPTED: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);  		bfa_fcs_rport_send_adisc(rport, NULL);  		break; @@ -663,24 +759,24 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)  			bfa_fcs_rport_send_nsdisc(rport, NULL);  		} else {  			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); -			bfa_fcs_rport_offline_action(rport); +			bfa_fcs_rport_hal_offline_action(rport);  		}  		break;  	case RPSM_EVENT_DELETE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		break;  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_PLOGI_COMP: @@ -689,7 +785,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)  	case RPSM_EVENT_LOGO_IMP:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	default: @@ -702,7 +798,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)   *	authenticating with rport. FC-4s are paused.   */  static void -bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, +bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,  	 enum rport_event event)  {  	bfa_trc(rport->fcs, rport->pwwn); @@ -711,36 +807,36 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,  	switch (event) {  	case RPSM_EVENT_FCXP_SENT: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);  		break;  	case RPSM_EVENT_DELETE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_LOGO_IMP:  	case RPSM_EVENT_ADDRESS_CHANGE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		break;  	case RPSM_EVENT_PLOGI_RCVD:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	default: @@ -753,7 +849,8 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,   *		FC-4s are paused.   */  static void -bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event) +bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport, +				enum rport_event event)  {  	bfa_trc(rport->fcs, rport->pwwn);  	bfa_trc(rport->fcs, rport->pid); @@ -777,16 +874,16 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)  	case RPSM_EVENT_FAILED:  	case RPSM_EVENT_ADDRESS_CHANGE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_DELETE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		/*  		 * already processing RSCN  		 */ @@ -795,14 +892,103 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)  	case RPSM_EVENT_LOGO_IMP:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport);  		break;  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_offline_action(rport); +		bfa_fcs_rport_hal_offline_action(rport); +		break; + +	default: +		bfa_sm_fault(rport->fcs, event); +	} +} + +/* + * ADISC is being sent for authenticating with rport + * Already did offline actions. + */ +static void +bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport, +	enum rport_event event) +{ +	bfa_trc(rport->fcs, rport->pwwn); +	bfa_trc(rport->fcs, rport->pid); +	bfa_trc(rport->fcs, event); + +	switch (event) { +	case RPSM_EVENT_FCXP_SENT: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline); +		break; + +	case RPSM_EVENT_DELETE: +	case RPSM_EVENT_SCN_OFFLINE: +	case RPSM_EVENT_LOGO_IMP: +	case RPSM_EVENT_LOGO_RCVD: +	case RPSM_EVENT_PRLO_RCVD: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); +		bfa_fcxp_walloc_cancel(rport->fcs->bfa, +			&rport->fcxp_wqe); +		bfa_timer_start(rport->fcs->bfa, &rport->timer, +			bfa_fcs_rport_timeout, rport, +			bfa_fcs_rport_del_timeout); +		break; + +	case RPSM_EVENT_PLOGI_RCVD: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); +		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); +		bfa_fcs_rport_send_plogiacc(rport, NULL); +		break; + +	default: +		bfa_sm_fault(rport->fcs, event); +	} +} + +/* + * ADISC to rport + * Already did offline actions + */ +static void +bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport, +			enum rport_event event) +{ +	bfa_trc(rport->fcs, rport->pwwn); +	bfa_trc(rport->fcs, rport->pid); +	bfa_trc(rport->fcs, event); + +	switch (event) { +	case RPSM_EVENT_ACCEPTED: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_fcs_rport_hal_online(rport); +		break; + +	case RPSM_EVENT_PLOGI_RCVD: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); +		bfa_fcxp_discard(rport->fcxp); +		bfa_fcs_rport_send_plogiacc(rport, NULL); +		break; + +	case RPSM_EVENT_FAILED: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); +		bfa_timer_start(rport->fcs->bfa, &rport->timer, +			bfa_fcs_rport_timeout, rport, +			bfa_fcs_rport_del_timeout); +		break; + +	case RPSM_EVENT_DELETE: +	case RPSM_EVENT_SCN_OFFLINE: +	case RPSM_EVENT_LOGO_IMP: +	case RPSM_EVENT_LOGO_RCVD: +	case RPSM_EVENT_PRLO_RCVD: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); +		bfa_fcxp_discard(rport->fcxp); +		bfa_timer_start(rport->fcs->bfa, &rport->timer, +			bfa_fcs_rport_timeout, rport, +			bfa_fcs_rport_del_timeout);  		break;  	default: @@ -811,7 +997,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)  }  /* - *		Rport has sent LOGO. Awaiting FC-4 offline completion callback. + * Rport has sent LOGO. Awaiting FC-4 offline completion callback.   */  static void  bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, @@ -824,13 +1010,21 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,  	switch (event) {  	case RPSM_EVENT_FC4_OFFLINE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); -		bfa_rport_offline(rport->bfa_rport); +		bfa_fcs_rport_hal_offline(rport);  		break;  	case RPSM_EVENT_DELETE: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); +		if (rport->pid && (rport->prlo == BFA_TRUE)) +			bfa_fcs_rport_send_prlo_acc(rport); +		if (rport->pid && (rport->prlo == BFA_FALSE)) +			bfa_fcs_rport_send_logo_acc(rport); + +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);  		break; +	case RPSM_EVENT_SCN_ONLINE: +	case RPSM_EVENT_SCN_OFFLINE: +	case RPSM_EVENT_HCB_ONLINE:  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  	case RPSM_EVENT_ADDRESS_CHANGE: @@ -856,7 +1050,20 @@ bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,  	switch (event) {  	case RPSM_EVENT_FC4_OFFLINE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); -		bfa_rport_offline(rport->bfa_rport); +		bfa_fcs_rport_hal_offline(rport); +		break; + +	case RPSM_EVENT_LOGO_RCVD: +		bfa_fcs_rport_send_logo_acc(rport); +	case RPSM_EVENT_PRLO_RCVD: +		if (rport->prlo == BFA_TRUE) +			bfa_fcs_rport_send_prlo_acc(rport); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete); +		break; + +	case RPSM_EVENT_HCB_ONLINE: +	case RPSM_EVENT_DELETE: +		/* Rport is being deleted */  		break;  	default: @@ -878,13 +1085,26 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,  	switch (event) {  	case RPSM_EVENT_FC4_OFFLINE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); -		bfa_rport_offline(rport->bfa_rport); +		bfa_fcs_rport_hal_offline(rport);  		break; -	case RPSM_EVENT_SCN: -	case RPSM_EVENT_LOGO_IMP: +	case RPSM_EVENT_SCN_ONLINE: +		break;  	case RPSM_EVENT_LOGO_RCVD: +		/* +		 * Rport is going offline. Just ack the logo +		 */ +		bfa_fcs_rport_send_logo_acc(rport); +		break; +  	case RPSM_EVENT_PRLO_RCVD: +		bfa_fcs_rport_send_prlo_acc(rport); +		break; + +	case RPSM_EVENT_SCN_OFFLINE: +	case RPSM_EVENT_HCB_ONLINE: +	case RPSM_EVENT_FAB_SCN: +	case RPSM_EVENT_LOGO_IMP:  	case RPSM_EVENT_ADDRESS_CHANGE:  		/*  		 * rport is already going offline. @@ -915,25 +1135,49 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,  	switch (event) {  	case RPSM_EVENT_HCB_OFFLINE: +		if (bfa_fcs_lport_is_online(rport->port) && +		    (rport->plogi_pending)) { +			rport->plogi_pending = BFA_FALSE; +			bfa_sm_set_state(rport, +				bfa_fcs_rport_sm_plogiacc_sending); +			bfa_fcs_rport_send_plogiacc(rport, NULL); +			break; +		} +		/* +		 * !! fall through !! +		 */ +  	case RPSM_EVENT_ADDRESS_CHANGE: -		if (bfa_fcs_lport_is_online(rport->port)) { -			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { -				bfa_sm_set_state(rport, -					bfa_fcs_rport_sm_nsdisc_sending); -				rport->ns_retries = 0; -				bfa_fcs_rport_send_nsdisc(rport, NULL); -			} else { -				bfa_sm_set_state(rport, -					bfa_fcs_rport_sm_plogi_sending); -				rport->plogi_retries = 0; -				bfa_fcs_rport_send_plogi(rport, NULL); -			} -		} else { +		if (!bfa_fcs_lport_is_online(rport->port)) {  			rport->pid = 0;  			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);  			bfa_timer_start(rport->fcs->bfa, &rport->timer,  					bfa_fcs_rport_timeout, rport,  					bfa_fcs_rport_del_timeout); +			break; +		} +		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { +			bfa_sm_set_state(rport, +				bfa_fcs_rport_sm_nsdisc_sending); +			rport->ns_retries = 0; +			bfa_fcs_rport_send_nsdisc(rport, NULL); +		} else if (bfa_fcport_get_topology(rport->port->fcs->bfa) == +					BFA_PORT_TOPOLOGY_LOOP) { +			if (rport->scn_online) { +				bfa_sm_set_state(rport, +					bfa_fcs_rport_sm_adisc_offline_sending); +				bfa_fcs_rport_send_adisc(rport, NULL); +			} else { +				bfa_sm_set_state(rport, +					bfa_fcs_rport_sm_offline); +				bfa_timer_start(rport->fcs->bfa, &rport->timer, +					bfa_fcs_rport_timeout, rport, +					bfa_fcs_rport_del_timeout); +			} +		} else { +			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); +			rport->plogi_retries = 0; +			bfa_fcs_rport_send_plogi(rport, NULL);  		}  		break; @@ -942,9 +1186,13 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,  		bfa_fcs_rport_free(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_SCN_ONLINE: +	case RPSM_EVENT_SCN_OFFLINE: +	case RPSM_EVENT_FAB_SCN:  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD: +	case RPSM_EVENT_PLOGI_RCVD: +	case RPSM_EVENT_LOGO_IMP:  		/*  		 * Ignore, already offline.  		 */ @@ -981,10 +1229,18 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,  		 */  		if (bfa_fcs_lport_is_online(rport->port) &&  			(!BFA_FCS_PID_IS_WKA(rport->pid))) { -			bfa_sm_set_state(rport, -				bfa_fcs_rport_sm_nsdisc_sending); -			rport->ns_retries = 0; -			bfa_fcs_rport_send_nsdisc(rport, NULL); +			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { +				bfa_sm_set_state(rport, +					bfa_fcs_rport_sm_nsdisc_sending); +				rport->ns_retries = 0; +				bfa_fcs_rport_send_nsdisc(rport, NULL); +			} else { +				/* For N2N  Direct Attach, try to re-login */ +				bfa_sm_set_state(rport, +					bfa_fcs_rport_sm_plogi_sending); +				rport->plogi_retries = 0; +				bfa_fcs_rport_send_plogi(rport, NULL); +			}  		} else {  			/*  			 * if it is not a well known address, reset the @@ -1000,13 +1256,19 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,  		break;  	case RPSM_EVENT_DELETE: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending); +		if (rport->pid && (rport->prlo == BFA_TRUE)) +			bfa_fcs_rport_send_prlo_acc(rport); +		if (rport->pid && (rport->prlo == BFA_FALSE)) +			bfa_fcs_rport_send_logo_acc(rport);  		break;  	case RPSM_EVENT_LOGO_IMP:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);  		break; +	case RPSM_EVENT_SCN_ONLINE: +	case RPSM_EVENT_SCN_OFFLINE:  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  		/* @@ -1039,7 +1301,16 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,  		break;  	case RPSM_EVENT_LOGO_RCVD: +		bfa_fcs_rport_send_logo_acc(rport);  	case RPSM_EVENT_PRLO_RCVD: +		if (rport->prlo == BFA_TRUE) +			bfa_fcs_rport_send_prlo_acc(rport); + +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending); +		break; + +	case RPSM_EVENT_SCN_ONLINE: +	case RPSM_EVENT_SCN_OFFLINE:  	case RPSM_EVENT_ADDRESS_CHANGE:  		break; @@ -1066,12 +1337,18 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,  		bfa_fcs_rport_free(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_SCN_ONLINE: +	case RPSM_EVENT_SCN_OFFLINE: +	case RPSM_EVENT_FAB_SCN:  	case RPSM_EVENT_ADDRESS_CHANGE:  		break;  	case RPSM_EVENT_LOGO_RCVD: +		bfa_fcs_rport_send_logo_acc(rport);  	case RPSM_EVENT_PRLO_RCVD: +		if (rport->prlo == BFA_TRUE) +			bfa_fcs_rport_send_prlo_acc(rport); +  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);  		bfa_fcs_rport_free(rport); @@ -1099,10 +1376,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)  		bfa_fcs_rport_free(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  	case RPSM_EVENT_ADDRESS_CHANGE: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);  		bfa_timer_stop(&rport->timer); +		WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) != +					BFA_PORT_TOPOLOGY_LOOP)); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);  		rport->ns_retries = 0;  		bfa_fcs_rport_send_nsdisc(rport, NULL);  		break; @@ -1122,12 +1401,19 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  	case RPSM_EVENT_LOGO_IMP: +	case RPSM_EVENT_SCN_OFFLINE:  		break;  	case RPSM_EVENT_PLOGI_COMP: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);  		bfa_timer_stop(&rport->timer); -		bfa_fcs_rport_hal_online(rport); +		bfa_fcs_rport_fcs_online_action(rport); +		break; + +	case RPSM_EVENT_SCN_ONLINE: +		bfa_timer_stop(&rport->timer); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); +		bfa_fcs_rport_send_plogi(rport, NULL);  		break;  	case RPSM_EVENT_PLOGI_SEND: @@ -1170,7 +1456,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,  		bfa_fcs_rport_send_plogiacc(rport, NULL);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  	case RPSM_EVENT_LOGO_RCVD:  	case RPSM_EVENT_PRLO_RCVD:  	case RPSM_EVENT_PLOGI_SEND: @@ -1189,9 +1475,9 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,  		break;  	case RPSM_EVENT_PLOGI_COMP: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);  		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); -		bfa_fcs_rport_hal_online(rport); +		bfa_fcs_rport_fcs_online_action(rport);  		break;  	default: @@ -1216,7 +1502,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,  		bfa_fcs_rport_send_nsdisc(rport, NULL);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  	case RPSM_EVENT_ADDRESS_CHANGE:  		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);  		bfa_timer_stop(&rport->timer); @@ -1253,9 +1539,9 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,  		break;  	case RPSM_EVENT_PLOGI_COMP: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);  		bfa_timer_stop(&rport->timer); -		bfa_fcs_rport_hal_online(rport); +		bfa_fcs_rport_fcs_online_action(rport);  		break;  	default: @@ -1295,6 +1581,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,  				 bfa_fcs_rport_sm_nsdisc_sending);  			bfa_fcs_rport_send_nsdisc(rport, NULL);  		} else { +			rport->old_pid = rport->pid;  			rport->pid = 0;  			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);  			bfa_timer_start(rport->fcs->bfa, &rport->timer, @@ -1328,7 +1615,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,  	case RPSM_EVENT_PRLO_RCVD:  		bfa_fcs_rport_send_prlo_acc(rport);  		break; -	case RPSM_EVENT_SCN: +	case RPSM_EVENT_FAB_SCN:  		/*  		 * ignore, wait for NS query response  		 */ @@ -1342,9 +1629,9 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,  		break;  	case RPSM_EVENT_PLOGI_COMP: -		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);  		bfa_fcxp_discard(rport->fcxp); -		bfa_fcs_rport_hal_online(rport); +		bfa_fcs_rport_fcs_online_action(rport);  		break;  	default: @@ -1352,7 +1639,63 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,  	}  } +/* + * Rport needs to be deleted + * waiting for ITNIM clean up to finish + */ +static void +bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport, +				enum rport_event event) +{ +	bfa_trc(rport->fcs, rport->pwwn); +	bfa_trc(rport->fcs, rport->pid); +	bfa_trc(rport->fcs, event); + +	switch (event) { +	case RPSM_EVENT_FC4_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending); +		bfa_fcs_rport_hal_offline(rport); +		break; + +	case RPSM_EVENT_DELETE: +	case RPSM_EVENT_PLOGI_RCVD: +		/* Ignore these events */ +		break; + +	default: +		bfa_sm_fault(rport->fcs, event); +		break; +	} +} + +/* + * RPort needs to be deleted + * waiting for BFA/FW to finish current processing + */ +static void +bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport, +				enum rport_event event) +{ +	bfa_trc(rport->fcs, rport->pwwn); +	bfa_trc(rport->fcs, rport->pid); +	bfa_trc(rport->fcs, event); + +	switch (event) { +	case RPSM_EVENT_HCB_OFFLINE: +		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); +		bfa_fcs_rport_free(rport); +		break; +	case RPSM_EVENT_DELETE: +	case RPSM_EVENT_LOGO_IMP: +	case RPSM_EVENT_PLOGI_RCVD: +		/* Ignore these events */ +		break; + +	default: +		bfa_sm_fault(rport->fcs, event); +	} +}  /*   *  fcs_rport_private FCS RPORT provate functions @@ -1369,10 +1712,11 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(rport->fcs, rport->pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, -					bfa_fcs_rport_send_plogi, rport); +				bfa_fcs_rport_send_plogi, rport, BFA_TRUE);  		return;  	}  	rport->fcxp = fcxp; @@ -1380,7 +1724,8 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,  				bfa_fcs_lport_get_fcid(port), 0,  				port->port_cfg.pwwn, port->port_cfg.nwwn, -				bfa_fcport_get_maxfrsize(port->fcs->bfa)); +				bfa_fcport_get_maxfrsize(port->fcs->bfa), +				bfa_fcport_get_rx_bbcredit(port->fcs->bfa));  	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,  			FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response, @@ -1459,7 +1804,7 @@ bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,  			twin->stats.plogi_rcvd	  += rport->stats.plogi_rcvd;  			twin->stats.plogi_accs++; -			bfa_fcs_rport_delete(rport); +			bfa_sm_send_event(rport, RPSM_EVENT_DELETE);  			bfa_fcs_rport_update(twin, plogi_rsp);  			twin->pid = rsp_fchs->s_id; @@ -1488,10 +1833,11 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(rport->fcs, rport->pwwn);  	bfa_trc(rport->fcs, rport->reply_oxid); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, -					bfa_fcs_rport_send_plogiacc, rport); +				bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);  		return;  	}  	rport->fcxp = fcxp; @@ -1500,7 +1846,8 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)  				 rport->pid, bfa_fcs_lport_get_fcid(port),  				 rport->reply_oxid, port->port_cfg.pwwn,  				 port->port_cfg.nwwn, -				 bfa_fcport_get_maxfrsize(port->fcs->bfa)); +				 bfa_fcport_get_maxfrsize(port->fcs->bfa), +				 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));  	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,  			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); @@ -1519,10 +1866,11 @@ bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(rport->fcs, rport->pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, -					bfa_fcs_rport_send_adisc, rport); +				bfa_fcs_rport_send_adisc, rport, BFA_TRUE);  		return;  	}  	rport->fcxp = fcxp; @@ -1582,10 +1930,11 @@ bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(rport->fcs, rport->pid); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, -					bfa_fcs_rport_send_nsdisc, rport); +				bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);  		return;  	}  	rport->fcxp = fcxp; @@ -1738,10 +2087,11 @@ bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	port = rport->port; -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, -					bfa_fcs_rport_send_logo, rport); +				bfa_fcs_rport_send_logo, rport, BFA_FALSE);  		return;  	}  	rport->fcxp = fcxp; @@ -1775,7 +2125,7 @@ bfa_fcs_rport_send_logo_acc(void *rport_cbarg)  	port = rport->port; -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -1846,7 +2196,7 @@ bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,  		bfa_fcs_itnim_is_initiator(rport->itnim);  	} -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -1883,7 +2233,7 @@ bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,  	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed); -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -1917,7 +2267,7 @@ bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,  	 */  	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) { -		fcxp = bfa_fcs_fcxp_alloc(port->fcs); +		fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  		if (!fcxp)  			return; @@ -1954,6 +2304,15 @@ bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)  	bfa_rport_online(rport->bfa_rport, &rport_info);  } +static void +bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport) +{ +	if (rport->bfa_rport) +		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); +	else +		bfa_cb_rport_offline(rport); +} +  static struct bfa_fcs_rport_s *  bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)  { @@ -1964,6 +2323,11 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)  	/*  	 * allocate rport  	 */ +	if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) { +		bfa_trc(fcs, rpid); +		return NULL; +	} +  	if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)  		!= BFA_STATUS_OK) {  		bfa_trc(fcs, rpid); @@ -1978,33 +2342,26 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)  	rport->rp_drv = rport_drv;  	rport->pid = rpid;  	rport->pwwn = pwwn; +	rport->old_pid = 0; -	/* -	 * allocate BFA rport -	 */ -	rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport); -	if (!rport->bfa_rport) { -		bfa_trc(fcs, rpid); -		kfree(rport_drv); -		return NULL; -	} +	rport->bfa_rport = NULL;  	/*  	 * allocate FC-4s  	 */ -	bfa_assert(bfa_fcs_lport_is_initiator(port)); +	WARN_ON(!bfa_fcs_lport_is_initiator(port));  	if (bfa_fcs_lport_is_initiator(port)) {  		rport->itnim = bfa_fcs_itnim_create(rport);  		if (!rport->itnim) {  			bfa_trc(fcs, rpid); -			bfa_rport_delete(rport->bfa_rport);  			kfree(rport_drv);  			return NULL;  		}  	}  	bfa_fcs_lport_add_rport(port, rport); +	fcs->num_rport_logins++;  	bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); @@ -2020,25 +2377,73 @@ static void  bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)  {  	struct bfa_fcs_lport_s *port = rport->port; +	struct bfa_fcs_s *fcs = port->fcs;  	/*  	 * - delete FC-4s  	 * - delete BFA rport  	 * - remove from queue of rports  	 */ +	rport->plogi_pending = BFA_FALSE; +  	if (bfa_fcs_lport_is_initiator(port)) {  		bfa_fcs_itnim_delete(rport->itnim);  		if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))  			bfa_fcs_rpf_rport_offline(rport);  	} -	bfa_rport_delete(rport->bfa_rport); +	if (rport->bfa_rport) { +		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE); +		rport->bfa_rport = NULL; +	} +  	bfa_fcs_lport_del_rport(port, rport); +	fcs->num_rport_logins--;  	kfree(rport->rp_drv);  }  static void -bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport) +bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport, +			enum bfa_rport_aen_event event, +			struct bfa_rport_aen_data_s *data) +{ +	struct bfa_fcs_lport_s *port = rport->port; +	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; +	struct bfa_aen_entry_s  *aen_entry; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	if (event == BFA_RPORT_AEN_QOS_PRIO) +		aen_entry->aen_data.rport.priv.qos = data->priv.qos; +	else if (event == BFA_RPORT_AEN_QOS_FLOWID) +		aen_entry->aen_data.rport.priv.qos = data->priv.qos; + +	aen_entry->aen_data.rport.vf_id = rport->port->fabric->vf_id; +	aen_entry->aen_data.rport.ppwwn = bfa_fcs_lport_get_pwwn( +					bfa_fcs_get_base_port(rport->fcs)); +	aen_entry->aen_data.rport.lpwwn = bfa_fcs_lport_get_pwwn(rport->port); +	aen_entry->aen_data.rport.rpwwn = rport->pwwn; + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq, +				  BFA_AEN_CAT_RPORT, event); +} + +static void +bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport) +{ +	if ((!rport->pid) || (!rport->pwwn)) { +		bfa_trc(rport->fcs, rport->pid); +		bfa_sm_fault(rport->fcs, rport->pid); +	} + +	bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE); +} + +static void +bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)  {  	struct bfa_fcs_lport_s *port = rport->port;  	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad; @@ -2047,43 +2452,69 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)  	rport->stats.onlines++; +	if ((!rport->pid) || (!rport->pwwn)) { +		bfa_trc(rport->fcs, rport->pid); +		bfa_sm_fault(rport->fcs, rport->pid); +	} +  	if (bfa_fcs_lport_is_initiator(port)) { -		bfa_fcs_itnim_rport_online(rport->itnim); +		bfa_fcs_itnim_brp_online(rport->itnim);  		if (!BFA_FCS_PID_IS_WKA(rport->pid))  			bfa_fcs_rpf_rport_online(rport);  	};  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));  	wwn2str(rpwwn_buf, rport->pwwn); -	if (!BFA_FCS_PID_IS_WKA(rport->pid)) -		BFA_LOG(KERN_INFO, bfad, log_level, +	if (!BFA_FCS_PID_IS_WKA(rport->pid)) { +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"Remote port (WWN = %s) online for logical port (WWN = %s)\n",  		rpwwn_buf, lpwwn_buf); +		bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL); +	} +} + +static void +bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport) +{ +	if (!BFA_FCS_PID_IS_WKA(rport->pid)) +		bfa_fcs_rpf_rport_offline(rport); + +	bfa_fcs_itnim_rport_offline(rport->itnim);  }  static void -bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport) +bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)  {  	struct bfa_fcs_lport_s *port = rport->port;  	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;  	char	lpwwn_buf[BFA_STRING_32];  	char	rpwwn_buf[BFA_STRING_32]; +	if (!rport->bfa_rport) { +		bfa_fcs_rport_fcs_offline_action(rport); +		return; +	} +  	rport->stats.offlines++;  	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));  	wwn2str(rpwwn_buf, rport->pwwn);  	if (!BFA_FCS_PID_IS_WKA(rport->pid)) { -		if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) -			BFA_LOG(KERN_ERR, bfad, log_level, +		if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) { +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Remote port (WWN = %s) connectivity lost for "  				"logical port (WWN = %s)\n",  				rpwwn_buf, lpwwn_buf); -		else -			BFA_LOG(KERN_INFO, bfad, log_level, +			bfa_fcs_rport_aen_post(rport, +				BFA_RPORT_AEN_DISCONNECT, NULL); +		} else { +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Remote port (WWN = %s) offlined by "  				"logical port (WWN = %s)\n",  				rpwwn_buf, lpwwn_buf); +			bfa_fcs_rport_aen_post(rport, +				BFA_RPORT_AEN_OFFLINE, NULL); +		}  	}  	if (bfa_fcs_lport_is_initiator(port)) { @@ -2123,7 +2554,10 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)  	 * - MAX receive frame size  	 */  	rport->cisc = plogi->csp.cisc; -	rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz); +	if (be16_to_cpu(plogi->class3.rxsz) < be16_to_cpu(plogi->csp.rxsz)) +		rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz); +	else +		rport->maxfrsize = be16_to_cpu(plogi->csp.rxsz);  	bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));  	bfa_trc(port->fcs, port->fabric->bb_credit); @@ -2256,22 +2690,6 @@ bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,  	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);  } -static int -wwn_compare(wwn_t wwn1, wwn_t wwn2) -{ -	u8		*b1 = (u8 *) &wwn1; -	u8		*b2 = (u8 *) &wwn2; -	int		i; - -	for (i = 0; i < sizeof(wwn_t); i++) { -		if (b1[i] < b2[i]) -			return -1; -		if (b1[i] > b2[i]) -			return 1; -	} -	return 0; -} -  /*   *	Called by bport/vport to handle PLOGI received from an existing   *	 remote port. @@ -2289,83 +2707,22 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,  	rport->reply_oxid = rx_fchs->ox_id;  	bfa_trc(rport->fcs, rport->reply_oxid); -	/* -	 * In Switched fabric topology, -	 * PLOGI to each other. If our pwwn is smaller, ignore it, -	 * if it is not a well known address. -	 * If the link topology is N2N, -	 * this Plogi should be accepted. -	 */ -	if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) && -		(bfa_fcs_fabric_is_switched(rport->port->fabric)) && -		(!BFA_FCS_PID_IS_WKA(rport->pid))) { -		bfa_trc(rport->fcs, rport->pid); -		return; -	} +	rport->pid = rx_fchs->s_id; +	bfa_trc(rport->fcs, rport->pid);  	rport->stats.plogi_rcvd++;  	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);  } -/* - * Called by bport/vport to delete a remote port instance. - * - * Rport delete is called under the following conditions: - *		- vport is deleted - *		- vf is deleted - *		- explicit request from OS to delete rport - */ -void -bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport) -{ -	bfa_sm_send_event(rport, RPSM_EVENT_DELETE); -} - -/* - * Called by bport/vport to  when a target goes offline. - * - */ -void -bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport) -{ -	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); -}  /* - * Called by bport in n2n when a target (attached port) becomes online. - * - */ -void -bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport) -{ -	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); -} -/*   *	Called by bport/vport to notify SCN for the remote port   */  void  bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)  {  	rport->stats.rscns++; -	bfa_sm_send_event(rport, RPSM_EVENT_SCN); -} - -/* - *	Called by	fcpim to notify that the ITN cleanup is done. - */ -void -bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport) -{ -	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); -} - -/* - *	Called by fcptm to notify that the ITN cleanup is done. - */ -void -bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport) -{ -	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); +	bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);  }  /* @@ -2433,8 +2790,53 @@ bfa_cb_rport_qos_scn_flowid(void *cbarg,  		struct bfa_rport_qos_attr_s new_qos_attr)  {  	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg; +	struct bfa_rport_aen_data_s aen_data;  	bfa_trc(rport->fcs, rport->pwwn); +	aen_data.priv.qos = new_qos_attr; +	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data); +} + +void +bfa_cb_rport_scn_online(struct bfa_s *bfa) +{ +	struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs; +	struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs); +	struct bfa_fcs_rport_s *rp; +	struct list_head *qe; + +	list_for_each(qe, &port->rport_q) { +		rp = (struct bfa_fcs_rport_s *) qe; +		bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE); +		rp->scn_online = BFA_TRUE; +	} + +	if (bfa_fcs_lport_is_online(port)) +		bfa_fcs_lport_lip_scn_online(port); +} + +void +bfa_cb_rport_scn_no_dev(void *rport) +{ +	struct bfa_fcs_rport_s *rp = rport; + +	bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE); +	rp->scn_online = BFA_FALSE; +} + +void +bfa_cb_rport_scn_offline(struct bfa_s *bfa) +{ +	struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs; +	struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs); +	struct bfa_fcs_rport_s *rp; +	struct list_head *qe; + +	list_for_each(qe, &port->rport_q) { +		rp = (struct bfa_fcs_rport_s *) qe; +		bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE); +		rp->scn_online = BFA_FALSE; +	}  }  /* @@ -2457,17 +2859,11 @@ bfa_cb_rport_qos_scn_prio(void *cbarg,  		struct bfa_rport_qos_attr_s new_qos_attr)  {  	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg; +	struct bfa_rport_aen_data_s aen_data;  	bfa_trc(rport->fcs, rport->pwwn); -} - -/* - *		Called to process any unsolicted frames from this remote port - */ -void -bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport) -{ -	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); +	aen_data.priv.qos = new_qos_attr; +	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);  }  /* @@ -2538,7 +2934,7 @@ bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)  	bfa_trc(rport->fcs, rport->pid); -	fcxp = bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);  	if (!fcxp)  		return;  	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), @@ -2564,7 +2960,7 @@ bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,  	bfa_trc(rport->fcs, rx_fchs->s_id); -	fcxp = bfa_fcs_fcxp_alloc(rport->fcs); +	fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);  	if (!fcxp)  		return; @@ -2586,6 +2982,7 @@ bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)  	return bfa_sm_to_state(rport_sm_table, rport->sm);  } +  /*   *	brief   *		 Called by the Driver to set rport delete/ageout timeout @@ -2602,7 +2999,7 @@ bfa_fcs_rport_set_del_timeout(u8 rport_tmo)  		bfa_fcs_rport_del_timeout = rport_tmo * 1000;  }  void -bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id) +bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)  {  	bfa_trc(rport->fcs, rport->pid); @@ -2611,70 +3008,30 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)  	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);  } - - -/* - * Remote port implementation. - */ -  /* - *  fcs_rport_api FCS rport API. + * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation + * which limits number of concurrent logins to remote ports   */ - -/* - *	Direct API to add a target by port wwn. This interface is used, for - *	example, by bios when target pwwn is known from boot lun configuration. - */ -bfa_status_t -bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn, -		struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv) -{ -	bfa_trc(port->fcs, *pwwn); - -	return BFA_STATUS_OK; -} - -/* - *	Direct API to remove a target and its associated resources. This - *	interface is used, for example, by driver to remove target - *	ports from the target list for a VM. - */ -bfa_status_t -bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in) +void +bfa_fcs_rport_set_max_logins(u32 max_logins)  { - -	struct bfa_fcs_rport_s *rport; - -	bfa_trc(rport_in->fcs, rport_in->pwwn); - -	rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn); -	if (rport == NULL) { -		/* -		 * TBD Error handling -		 */ -		bfa_trc(rport_in->fcs, rport_in->pid); -		return BFA_STATUS_UNKNOWN_RWWN; -	} - -	/* -	 * TBD if this remote port is online, send a logo -	 */ -	return BFA_STATUS_OK; - +	if (max_logins > 0) +		bfa_fcs_rport_max_logins = max_logins;  } -/* - *	Remote device status for display/debug. - */  void  bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, -			struct bfa_rport_attr_s *rport_attr) +		struct bfa_rport_attr_s *rport_attr)  {  	struct bfa_rport_qos_attr_s qos_attr; -	bfa_fcs_lport_t *port = rport->port; +	struct bfa_fcs_lport_s *port = rport->port;  	bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed; +	struct bfa_port_attr_s port_attr; + +	bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);  	memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s)); +	memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));  	rport_attr->pid = rport->pid;  	rport_attr->pwwn = rport->pwwn; @@ -2688,38 +3045,33 @@ bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,  	rport_attr->curr_speed  = rport->rpf.rpsc_speed;  	rport_attr->assigned_speed  = rport->rpf.assigned_speed; -	bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr); +	if (rport->bfa_rport) { +		qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority; +		qos_attr.qos_flow_id = +			cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id); +	}  	rport_attr->qos_attr = qos_attr;  	rport_attr->trl_enforced = BFA_FALSE; -	if (bfa_fcport_is_ratelim(port->fcs->bfa)) { -		if (rport_speed == BFA_PORT_SPEED_UNKNOWN) { -			/* Use default ratelim speed setting */ +	if (bfa_fcport_is_ratelim(port->fcs->bfa) && +	    (rport->scsi_function == BFA_RPORT_TARGET)) { +		if (rport_speed == BFA_PORT_SPEED_UNKNOWN)  			rport_speed =  				bfa_fcport_get_ratelim_speed(rport->fcs->bfa); -		} -		if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port)) +		if ((bfa_fcs_lport_get_rport_max_speed(port) != +		    BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))  			rport_attr->trl_enforced = BFA_TRUE;  	}  }  /* - *	Per remote device statistics. + * Remote port implementation.   */ -void -bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport, -			struct bfa_rport_stats_s *stats) -{ -	*stats = rport->stats; -} -void -bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport) -{ -	memset((char *)&rport->stats, 0, -			sizeof(struct bfa_rport_stats_s)); -} +/* + *  fcs_rport_api FCS rport API. + */  struct bfa_fcs_rport_s *  bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn) @@ -2752,22 +3104,6 @@ bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)  }  /* - * This API is to set the Rport's speed. Should be used when RPSC is not - * supported by the rport. - */ -void -bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed) -{ -	rport->rpf.assigned_speed  = speed; - -	/* Set this speed in f/w only if the RPSC speed is not available */ -	if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN) -		bfa_rport_speed(rport->bfa_rport, speed); -} - - - -/*   * Remote port features (RPF) implementation.   */ @@ -2827,7 +3163,7 @@ bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)  	case RPFSM_EVENT_RPORT_ONLINE:  		/* Send RPSC2 to a Brocade fabric only. */  		if ((!BFA_FCS_PID_IS_WKA(rport->pid)) && -			((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) || +			((rport->port->fabric->lps->brcd_switch) ||  			(bfa_fcs_fabric_get_switch_oui(fabric) ==  						BFA_FCS_BRCD_SWITCH_OUI))) {  			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); @@ -3047,10 +3383,11 @@ bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)  	bfa_trc(rport->fcs, rport->pwwn); -	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); +	fcxp = fcxp_alloced ? fcxp_alloced : +	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);  	if (!fcxp) {  		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe, -					bfa_fcs_rpf_send_rpsc2, rpf); +				bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);  		return;  	}  	rpf->fcxp = fcxp; @@ -3093,9 +3430,10 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,  		num_ents = be16_to_cpu(rpsc2_acc->num_pids);  		bfa_trc(rport->fcs, num_ents);  		if (num_ents > 0) { -			bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid); +			WARN_ON(be32_to_cpu(rpsc2_acc->port_info[0].pid) != +						bfa_ntoh3b(rport->pid));  			bfa_trc(rport->fcs, -				be16_to_cpu(rpsc2_acc->port_info[0].pid)); +				be32_to_cpu(rpsc2_acc->port_info[0].pid));  			bfa_trc(rport->fcs,  				be16_to_cpu(rpsc2_acc->port_info[0].speed));  			bfa_trc(rport->fcs, diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c index d8464ae6007..ea24d4c6e67 100644 --- a/drivers/scsi/bfa/bfa_hw_cb.c +++ b/drivers/scsi/bfa/bfa_hw_cb.c @@ -15,15 +15,16 @@   * General Public License for more details.   */ +#include "bfad_drv.h"  #include "bfa_modules.h" -#include "bfi_cbreg.h" +#include "bfi_reg.h"  void  bfa_hwcb_reginit(struct bfa_s *bfa)  {  	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;  	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); -	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc); +	int	fn = bfa_ioc_pcifn(&bfa->ioc);  	if (fn == 0) {  		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); @@ -32,29 +33,6 @@ bfa_hwcb_reginit(struct bfa_s *bfa)  		bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);  		bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);  	} - -	for (i = 0; i < BFI_IOC_MAX_CQS; i++) { -		/* -		 * CPE registers -		 */ -		q = CPE_Q_NUM(fn, i); -		bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q)); -		bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q)); -		bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q)); - -		/* -		 * RME registers -		 */ -		q = CPE_Q_NUM(fn, i); -		bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q)); -		bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q)); -		bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q)); -	} -} - -void -bfa_hwcb_reqq_ack(struct bfa_s *bfa, int reqq) -{  }  static void @@ -64,16 +42,36 @@ bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)  			bfa->iocfc.bfa_regs.intr_status);  } -void -bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq) +/* + * Actions to respond RME Interrupt for Crossbow ASIC: + * - Write 1 to Interrupt Status register + *              INTX - done in bfa_intx() + *              MSIX - done in bfa_hwcb_rspq_ack_msix() + * - Update CI (only if new CI) + */ +static void +bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci)  { +	writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq), +		bfa->iocfc.bfa_regs.intr_status); + +	if (bfa_rspq_ci(bfa, rspq) == ci) +		return; + +	bfa_rspq_ci(bfa, rspq) = ci; +	writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); +	mmiowb();  } -static void -bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq) +void +bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)  { -	writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq), -			bfa->iocfc.bfa_regs.intr_status); +	if (bfa_rspq_ci(bfa, rspq) == ci) +		return; + +	bfa_rspq_ci(bfa, rspq) = ci; +	writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); +	mmiowb();  }  void @@ -103,43 +101,71 @@ bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,  }  /* + * Dummy interrupt handler for handling spurious interrupts. + */ +static void +bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec) +{ +} + +/*   * No special setup required for crossbow -- vector assignments are implicit.   */  void  bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)  { +	WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS)); + +	bfa->msix.nvecs = nvecs; +	bfa_hwcb_msix_uninstall(bfa); +} + +void +bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa) +{  	int i; -	bfa_assert((nvecs == 1) || (nvecs == __HFN_NUMINTS)); +	if (bfa->msix.nvecs == 0) +		return; -	bfa->msix.nvecs = nvecs; -	if (nvecs == 1) { -		for (i = 0; i < BFA_MSIX_CB_MAX; i++) +	if (bfa->msix.nvecs == 1) { +		for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++)  			bfa->msix.handler[i] = bfa_msix_all;  		return;  	} -	for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++) -		bfa->msix.handler[i] = bfa_msix_reqq; - -	for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++) -		bfa->msix.handler[i] = bfa_msix_rspq; - -	for (; i < BFA_MSIX_CB_MAX; i++) +	for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)  		bfa->msix.handler[i] = bfa_msix_lpu_err;  } -/* - * Crossbow -- dummy, interrupts are masked - */  void -bfa_hwcb_msix_install(struct bfa_s *bfa) +bfa_hwcb_msix_queue_install(struct bfa_s *bfa)  { +	int i; + +	if (bfa->msix.nvecs == 0) +		return; + +	if (bfa->msix.nvecs == 1) { +		for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) +			bfa->msix.handler[i] = bfa_msix_all; +		return; +	} + +	for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++) +		bfa->msix.handler[i] = bfa_msix_reqq; + +	for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++) +		bfa->msix.handler[i] = bfa_msix_rspq;  }  void  bfa_hwcb_msix_uninstall(struct bfa_s *bfa)  { +	int i; + +	for (i = 0; i < BFI_MSIX_CB_MAX; i++) +		bfa->msix.handler[i] = bfa_hwcb_msix_dummy;  }  /* @@ -148,13 +174,18 @@ bfa_hwcb_msix_uninstall(struct bfa_s *bfa)  void  bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)  { -	bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix; -	bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; +	if (msix) { +		bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix; +		bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; +	} else { +		bfa->iocfc.hwif.hw_reqq_ack = NULL; +		bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; +	}  }  void  bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)  { -	*start = BFA_MSIX_RME_Q0; -	*end = BFA_MSIX_RME_Q7; +	*start = BFI_MSIX_RME_QMIN_CB; +	*end = BFI_MSIX_RME_QMAX_CB;  } diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c index b0efbc713ff..637527f48b4 100644 --- a/drivers/scsi/bfa/bfa_hw_ct.c +++ b/drivers/scsi/bfa/bfa_hw_ct.c @@ -15,30 +15,12 @@   * General Public License for more details.   */ +#include "bfad_drv.h"  #include "bfa_modules.h" -#include "bfi_ctreg.h" +#include "bfi_reg.h"  BFA_TRC_FILE(HAL, IOCFC_CT); -static u32 __ct_msix_err_vec_reg[] = { -	HOST_MSIX_ERR_INDEX_FN0, -	HOST_MSIX_ERR_INDEX_FN1, -	HOST_MSIX_ERR_INDEX_FN2, -	HOST_MSIX_ERR_INDEX_FN3, -}; - -static void -bfa_hwct_msix_lpu_err_set(struct bfa_s *bfa, bfa_boolean_t msix, int vec) -{ -	int fn = bfa_ioc_pcifn(&bfa->ioc); -	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); - -	if (msix) -		writel(vec, kva + __ct_msix_err_vec_reg[fn]); -	else -		writel(0, kva + __ct_msix_err_vec_reg[fn]); -} -  /*   * Dummy interrupt handler for handling spurious interrupt during chip-reinit.   */ @@ -52,7 +34,7 @@ bfa_hwct_reginit(struct bfa_s *bfa)  {  	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;  	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc); -	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc); +	int	fn = bfa_ioc_pcifn(&bfa->ioc);  	if (fn == 0) {  		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); @@ -61,26 +43,16 @@ bfa_hwct_reginit(struct bfa_s *bfa)  		bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);  		bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);  	} +} -	for (i = 0; i < BFI_IOC_MAX_CQS; i++) { -		/* -		 * CPE registers -		 */ -		q = CPE_Q_NUM(fn, i); -		bfa_regs->cpe_q_pi[i] = (kva + CPE_PI_PTR_Q(q << 5)); -		bfa_regs->cpe_q_ci[i] = (kva + CPE_CI_PTR_Q(q << 5)); -		bfa_regs->cpe_q_depth[i] = (kva + CPE_DEPTH_Q(q << 5)); -		bfa_regs->cpe_q_ctrl[i] = (kva + CPE_QCTRL_Q(q << 5)); - -		/* -		 * RME registers -		 */ -		q = CPE_Q_NUM(fn, i); -		bfa_regs->rme_q_pi[i] = (kva + RME_PI_PTR_Q(q << 5)); -		bfa_regs->rme_q_ci[i] = (kva + RME_CI_PTR_Q(q << 5)); -		bfa_regs->rme_q_depth[i] = (kva + RME_DEPTH_Q(q << 5)); -		bfa_regs->rme_q_ctrl[i] = (kva + RME_QCTRL_Q(q << 5)); -	} +void +bfa_hwct2_reginit(struct bfa_s *bfa) +{ +	struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; +	void __iomem	*kva = bfa_ioc_bar0(&bfa->ioc); + +	bfa_regs->intr_status = (kva + CT2_HOSTFN_INT_STATUS); +	bfa_regs->intr_mask   = (kva + CT2_HOSTFN_INTR_MASK);  }  void @@ -92,22 +64,45 @@ bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq)  	writel(r32, bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]);  } +/* + * Actions to respond RME Interrupt for Catapult ASIC: + * - Write 1 to Interrupt Status register (INTx only - done in bfa_intx()) + * - Acknowledge by writing to RME Queue Control register + * - Update CI + */  void -bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq) +bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)  {  	u32	r32;  	r32 = readl(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]);  	writel(r32, bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]); + +	bfa_rspq_ci(bfa, rspq) = ci; +	writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); +	mmiowb(); +} + +/* + * Actions to respond RME Interrupt for Catapult2 ASIC: + * - Write 1 to Interrupt Status register (INTx only - done in bfa_intx()) + * - Update CI + */ +void +bfa_hwct2_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci) +{ +	bfa_rspq_ci(bfa, rspq) = ci; +	writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]); +	mmiowb();  }  void  bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,  		 u32 *num_vecs, u32 *max_vec_bit)  { -	*msix_vecs_bmap = (1 << BFA_MSIX_CT_MAX) - 1; -	*max_vec_bit = (1 << (BFA_MSIX_CT_MAX - 1)); -	*num_vecs = BFA_MSIX_CT_MAX; +	*msix_vecs_bmap = (1 << BFI_MSIX_CT_MAX) - 1; +	*max_vec_bit = (1 << (BFI_MSIX_CT_MAX - 1)); +	*num_vecs = BFI_MSIX_CT_MAX;  }  /* @@ -116,7 +111,7 @@ bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,  void  bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)  { -	bfa_assert((nvecs == 1) || (nvecs == BFA_MSIX_CT_MAX)); +	WARN_ON((nvecs != 1) && (nvecs != BFI_MSIX_CT_MAX));  	bfa_trc(bfa, nvecs);  	bfa->msix.nvecs = nvecs; @@ -124,7 +119,19 @@ bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)  }  void -bfa_hwct_msix_install(struct bfa_s *bfa) +bfa_hwct_msix_ctrl_install(struct bfa_s *bfa) +{ +	if (bfa->msix.nvecs == 0) +		return; + +	if (bfa->msix.nvecs == 1) +		bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_all; +	else +		bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_lpu_err; +} + +void +bfa_hwct_msix_queue_install(struct bfa_s *bfa)  {  	int i; @@ -132,19 +139,16 @@ bfa_hwct_msix_install(struct bfa_s *bfa)  		return;  	if (bfa->msix.nvecs == 1) { -		for (i = 0; i < BFA_MSIX_CT_MAX; i++) +		for (i = BFI_MSIX_CPE_QMIN_CT; i < BFI_MSIX_CT_MAX; i++)  			bfa->msix.handler[i] = bfa_msix_all;  		return;  	} -	for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q3; i++) +	for (i = BFI_MSIX_CPE_QMIN_CT; i <= BFI_MSIX_CPE_QMAX_CT; i++)  		bfa->msix.handler[i] = bfa_msix_reqq; -	for (; i <= BFA_MSIX_RME_Q3; i++) +	for (i = BFI_MSIX_RME_QMIN_CT; i <= BFI_MSIX_RME_QMAX_CT; i++)  		bfa->msix.handler[i] = bfa_msix_rspq; - -	bfa_assert(i == BFA_MSIX_LPU_ERR); -	bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;  }  void @@ -152,7 +156,7 @@ bfa_hwct_msix_uninstall(struct bfa_s *bfa)  {  	int i; -	for (i = 0; i < BFA_MSIX_CT_MAX; i++) +	for (i = 0; i < BFI_MSIX_CT_MAX; i++)  		bfa->msix.handler[i] = bfa_hwct_msix_dummy;  } @@ -163,13 +167,12 @@ void  bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)  {  	bfa_trc(bfa, 0); -	bfa_hwct_msix_lpu_err_set(bfa, msix, BFA_MSIX_LPU_ERR);  	bfa_ioc_isr_mode_set(&bfa->ioc, msix);  }  void  bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)  { -	*start = BFA_MSIX_RME_Q0; -	*end = BFA_MSIX_RME_Q3; +	*start = BFI_MSIX_RME_QMIN_CT; +	*end = BFI_MSIX_RME_QMAX_CT;  } diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 54475b53a5a..315d6d6dcfc 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -15,11 +15,13 @@   * General Public License for more details.   */ +#include "bfad_drv.h" +#include "bfad_im.h"  #include "bfa_ioc.h" -#include "bfi_ctreg.h" +#include "bfi_reg.h"  #include "bfa_defs.h"  #include "bfa_defs_svc.h" -#include "bfad_drv.h" +#include "bfi.h"  BFA_TRC_FILE(CNA, IOC); @@ -29,8 +31,8 @@ BFA_TRC_FILE(CNA, IOC);  #define BFA_IOC_TOV		3000	/* msecs */  #define BFA_IOC_HWSEM_TOV	500	/* msecs */  #define BFA_IOC_HB_TOV		500	/* msecs */ -#define BFA_IOC_HWINIT_MAX	2  #define BFA_IOC_TOV_RECOVER	 BFA_IOC_HB_TOV +#define BFA_IOC_POLL_TOV	BFA_TIMER_FREQ  #define bfa_ioc_timer_start(__ioc)					\  	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\ @@ -42,13 +44,16 @@ BFA_TRC_FILE(CNA, IOC);  			bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)  #define bfa_hb_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->hb_timer) -#define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS) -#define BFA_DBG_FWTRC_LEN					\ -	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\ -	 (sizeof(struct bfa_trc_mod_s) -			\ -	  BFA_TRC_MAX * sizeof(struct bfa_trc_s)))  #define BFA_DBG_FWTRC_OFF(_fn)	(BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn)) +#define bfa_ioc_state_disabled(__sm)		\ +	(((__sm) == BFI_IOC_UNINIT) ||		\ +	((__sm) == BFI_IOC_INITING) ||		\ +	((__sm) == BFI_IOC_HWINIT) ||		\ +	((__sm) == BFI_IOC_DISABLED) ||		\ +	((__sm) == BFI_IOC_FAIL) ||		\ +	((__sm) == BFI_IOC_CFG_DISABLED)) +  /*   * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.   */ @@ -59,17 +64,26 @@ BFA_TRC_FILE(CNA, IOC);  			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))  #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))  #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) -#define bfa_ioc_notify_hbfail(__ioc)			\ -			((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc)) - -#ifdef BFA_IOC_IS_UEFI -#define bfa_ioc_is_bios_optrom(__ioc) (0) -#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI -#else -#define bfa_ioc_is_bios_optrom(__ioc)	\ -	(bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ) -#define bfa_ioc_is_uefi(__ioc) (0) -#endif +#define bfa_ioc_notify_fail(__ioc)              \ +			((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) +#define bfa_ioc_sync_start(__ioc)               \ +			((__ioc)->ioc_hwif->ioc_sync_start(__ioc)) +#define bfa_ioc_sync_join(__ioc)                \ +			((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) +#define bfa_ioc_sync_leave(__ioc)               \ +			((__ioc)->ioc_hwif->ioc_sync_leave(__ioc)) +#define bfa_ioc_sync_ack(__ioc)                 \ +			((__ioc)->ioc_hwif->ioc_sync_ack(__ioc)) +#define bfa_ioc_sync_complete(__ioc)            \ +			((__ioc)->ioc_hwif->ioc_sync_complete(__ioc)) +#define bfa_ioc_set_cur_ioc_fwstate(__ioc, __fwstate)		\ +			((__ioc)->ioc_hwif->ioc_set_fwstate(__ioc, __fwstate)) +#define bfa_ioc_get_cur_ioc_fwstate(__ioc)		\ +			((__ioc)->ioc_hwif->ioc_get_fwstate(__ioc)) +#define bfa_ioc_set_alt_ioc_fwstate(__ioc, __fwstate)		\ +		((__ioc)->ioc_hwif->ioc_set_alt_fwstate(__ioc, __fwstate)) +#define bfa_ioc_get_alt_ioc_fwstate(__ioc)		\ +			((__ioc)->ioc_hwif->ioc_get_alt_fwstate(__ioc))  #define bfa_ioc_mbox_cmd_pending(__ioc)		\  			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ @@ -81,29 +95,28 @@ bfa_boolean_t bfa_auto_recover = BFA_TRUE;   * forward declarations   */  static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc); -static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);  static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);  static void bfa_ioc_timeout(void *ioc); +static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);  static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);  static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);  static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);  static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc); -static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc); -static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);  static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc); -static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc); +static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);  static void bfa_ioc_recover(struct bfa_ioc_s *ioc); -static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc); +static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc , +				enum bfa_ioc_event_e event);  static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);  static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); -static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc); -static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc); -static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc); +static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);  static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); - -/* - *  hal_ioc_sm - */ +static enum bfi_ioc_img_ver_cmp_e bfa_ioc_fw_ver_patch_cmp( +				struct bfi_ioc_image_hdr_s *base_fwhdr, +				struct bfi_ioc_image_hdr_s *fwhdr_to_cmp); +static enum bfi_ioc_img_ver_cmp_e bfa_ioc_flash_fwver_cmp( +				struct bfa_ioc_s *ioc, +				struct bfi_ioc_image_hdr_s *base_fwhdr);  /*   * IOC state machine definitions/declarations @@ -116,10 +129,11 @@ enum ioc_event {  	IOC_E_ENABLED		= 5,	/*  f/w enabled		*/  	IOC_E_FWRSP_GETATTR	= 6,	/*  IOC get attribute response	*/  	IOC_E_DISABLED		= 7,	/*  f/w disabled		*/ -	IOC_E_FAILED		= 8,	/*  failure notice by iocpf sm	*/ +	IOC_E_PFFAILED		= 8,	/*  failure notice by iocpf sm	*/  	IOC_E_HBFAIL		= 9,	/*  heartbeat failure		*/  	IOC_E_HWERROR		= 10,	/*  hardware error interrupt	*/  	IOC_E_TIMEOUT		= 11,	/*  timeout			*/ +	IOC_E_HWFAILED		= 12,	/*  PCI mapping failure notice	*/  };  bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event); @@ -127,10 +141,11 @@ bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);  bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);  bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);  bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event); -bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);  bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);  bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);  bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);  static struct bfa_sm_table_s ioc_sm_table[] = {  	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT}, @@ -138,10 +153,11 @@ static struct bfa_sm_table_s ioc_sm_table[] = {  	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},  	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},  	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL}, -	{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL}, +	{BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},  	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},  	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},  	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, +	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},  };  /* @@ -153,9 +169,9 @@ static struct bfa_sm_table_s ioc_sm_table[] = {  			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)  #define bfa_iocpf_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->ioc_timer) -#define bfa_iocpf_recovery_timer_start(__ioc)				\ +#define bfa_iocpf_poll_timer_start(__ioc)				\  	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\ -			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER) +			bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)  #define bfa_sem_timer_start(__ioc)					\  	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,	\ @@ -165,14 +181,9 @@ static struct bfa_sm_table_s ioc_sm_table[] = {  /*   * Forward declareations for iocpf state machine   */ -static void bfa_iocpf_enable(struct bfa_ioc_s *ioc); -static void bfa_iocpf_disable(struct bfa_ioc_s *ioc); -static void bfa_iocpf_fail(struct bfa_ioc_s *ioc); -static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc); -static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc); -static void bfa_iocpf_stop(struct bfa_ioc_s *ioc);  static void bfa_iocpf_timeout(void *ioc_arg);  static void bfa_iocpf_sem_timeout(void *ioc_arg); +static void bfa_iocpf_poll_timeout(void *ioc_arg);  /*   * IOCPF state machine events @@ -189,6 +200,7 @@ enum iocpf_event {  	IOCPF_E_GETATTRFAIL	= 9,	/*  init fail notice by ioc sm	*/  	IOCPF_E_SEMLOCKED	= 10,	/*  h/w semaphore is locked	*/  	IOCPF_E_TIMEOUT		= 11,	/*  f/w response timeout	*/ +	IOCPF_E_SEM_ERROR	= 12,	/*  h/w sem mapping error	*/  };  /* @@ -213,9 +225,14 @@ bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);  bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);  bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);  bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event); +bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s, +						enum iocpf_event);  bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event); +bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event);  bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);  bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event); +bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s, +						enum iocpf_event);  bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);  static struct bfa_sm_table_s iocpf_sm_table[] = { @@ -226,9 +243,12 @@ static struct bfa_sm_table_s iocpf_sm_table[] = {  	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},  	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},  	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY}, +	{BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},  	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL}, +	{BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},  	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},  	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING}, +	{BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},  	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},  }; @@ -301,7 +321,7 @@ bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)  static void  bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)  { -	bfa_iocpf_enable(ioc); +	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);  }  /* @@ -318,13 +338,18 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)  		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);  		break; -	case IOC_E_FAILED: -		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); +	case IOC_E_PFFAILED: +		/* !!! fall through !!! */ +	case IOC_E_HWERROR: +		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); +		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); +		if (event != IOC_E_PFFAILED) +			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);  		break; -	case IOC_E_HWERROR: -		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); -		bfa_iocpf_initfail(ioc); +	case IOC_E_HWFAILED: +		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); +		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);  		break;  	case IOC_E_DISABLE: @@ -333,7 +358,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)  	case IOC_E_DETACH:  		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); -		bfa_iocpf_stop(ioc); +		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);  		break;  	case IOC_E_ENABLE: @@ -363,22 +388,18 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)  	switch (event) {  	case IOC_E_FWRSP_GETATTR:  		bfa_ioc_timer_stop(ioc); -		bfa_ioc_check_attr_wwns(ioc);  		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);  		break; -	case IOC_E_FAILED: -		bfa_ioc_timer_stop(ioc); -		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); -		break; - +	case IOC_E_PFFAILED:  	case IOC_E_HWERROR:  		bfa_ioc_timer_stop(ioc); -		/* fall through */ - +		/* !!! fall through !!! */  	case IOC_E_TIMEOUT: -		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); -		bfa_iocpf_getattrfail(ioc); +		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); +		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); +		if (event != IOC_E_PFFAILED) +			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);  		break;  	case IOC_E_DISABLE: @@ -394,15 +415,16 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)  	}  } -  static void  bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)  {  	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;  	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK); +	bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);  	bfa_ioc_hb_monitor(ioc); -	BFA_LOG(KERN_INFO, bfad, log_level, "IOC enabled\n"); +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n"); +	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);  }  static void @@ -415,22 +437,24 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)  		break;  	case IOC_E_DISABLE: -		bfa_ioc_hb_stop(ioc); +		bfa_hb_timer_stop(ioc);  		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);  		break; -	case IOC_E_FAILED: -		bfa_ioc_hb_stop(ioc); -		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); -		break; - +	case IOC_E_PFFAILED:  	case IOC_E_HWERROR: -		bfa_ioc_hb_stop(ioc); +		bfa_hb_timer_stop(ioc);  		/* !!! fall through !!! */ -  	case IOC_E_HBFAIL: -		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); -		bfa_iocpf_fail(ioc); +		if (ioc->iocpf.auto_recover) +			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); +		else +			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); + +		bfa_ioc_fail_notify(ioc); + +		if (event != IOC_E_PFFAILED) +			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);  		break;  	default: @@ -443,8 +467,9 @@ static void  bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)  {  	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; -	bfa_iocpf_disable(ioc); -	BFA_LOG(KERN_INFO, bfad, log_level, "IOC disabled\n"); +	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE); +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n"); +	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);  }  /* @@ -466,7 +491,12 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)  		 * after iocpf sm completes failure processing and  		 * moves to disabled state.  		 */ -		bfa_iocpf_fail(ioc); +		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); +		break; + +	case IOC_E_HWFAILED: +		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); +		bfa_ioc_disable_comp(ioc);  		break;  	default: @@ -499,7 +529,7 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)  	case IOC_E_DETACH:  		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); -		bfa_iocpf_stop(ioc); +		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);  		break;  	default: @@ -509,16 +539,16 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)  static void -bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc) +bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)  { -	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); +	bfa_trc(ioc, 0);  }  /* - * Hardware initialization failed. + * Hardware initialization retry.   */  static void -bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) +bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)  {  	bfa_trc(ioc, event); @@ -527,11 +557,23 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)  		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);  		break; -	case IOC_E_FAILED: +	case IOC_E_PFFAILED: +	case IOC_E_HWERROR:  		/* -		 * Initialization failure during iocpf init retry. +		 * Initialization retry failed.  		 */  		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); +		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); +		if (event != IOC_E_PFFAILED) +			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); +		break; + +	case IOC_E_HWFAILED: +		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); +		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); +		break; + +	case IOC_E_ENABLE:  		break;  	case IOC_E_DISABLE: @@ -540,7 +582,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)  	case IOC_E_DETACH:  		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); -		bfa_iocpf_stop(ioc); +		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);  		break;  	default: @@ -552,21 +594,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)  static void  bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)  { -	struct list_head			*qe; -	struct bfa_ioc_hbfail_notify_s	*notify; -	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; - -	/* -	 * Notify driver and common modules registered for notification. -	 */ -	ioc->cbfn->hbfail_cbfn(ioc->bfa); -	list_for_each(qe, &ioc->hb_notify_q) { -		notify = (struct bfa_ioc_hbfail_notify_s *) qe; -		notify->cbfn(notify->cbarg); -	} - -	BFA_LOG(KERN_CRIT, bfad, log_level, -		"Heart Beat of IOC has failed\n"); +	bfa_trc(ioc, 0);  }  /* @@ -579,26 +607,23 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)  	switch (event) { -	case IOC_E_FAILED: -		/* -		 * Initialization failure during iocpf recovery. -		 * !!! Fall through !!! -		 */  	case IOC_E_ENABLE:  		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);  		break; -	case IOC_E_ENABLED: -		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); -		break; -  	case IOC_E_DISABLE:  		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);  		break; +	case IOC_E_DETACH: +		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); +		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); +		break; +  	case IOC_E_HWERROR: +	case IOC_E_HWFAILED:  		/* -		 * HB failure notification, ignore. +		 * HB failure / HW error notification, ignore.  		 */  		break;  	default: @@ -606,20 +631,50 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)  	}  } +static void +bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc) +{ +	bfa_trc(ioc, 0); +} +static void +bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event) +{ +	bfa_trc(ioc, event); + +	switch (event) { +	case IOC_E_ENABLE: +		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); +		break; + +	case IOC_E_DISABLE: +		ioc->cbfn->disable_cbfn(ioc->bfa); +		break; + +	case IOC_E_DETACH: +		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); +		break; + +	case IOC_E_HWERROR: +		/* Ignore - already in hwfail state */ +		break; + +	default: +		bfa_sm_fault(ioc, event); +	} +}  /*   * IOCPF State Machine   */ -  /*   * Reset entry actions -- initialize state machine   */  static void  bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)  { -	iocpf->retry_count = 0; +	iocpf->fw_mismatch_notified = BFA_FALSE;  	iocpf->auto_recover = bfa_auto_recover;  } @@ -652,6 +707,61 @@ bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  static void  bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)  { +	struct bfi_ioc_image_hdr_s	fwhdr; +	u32	r32, fwstate, pgnum, pgoff, loff = 0; +	int	i; + +	/* +	 * Spin on init semaphore to serialize. +	 */ +	r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg); +	while (r32 & 0x1) { +		udelay(20); +		r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg); +	} + +	/* h/w sem init */ +	fwstate = bfa_ioc_get_cur_ioc_fwstate(iocpf->ioc); +	if (fwstate == BFI_IOC_UNINIT) { +		writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg); +		goto sem_get; +	} + +	bfa_ioc_fwver_get(iocpf->ioc, &fwhdr); + +	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) { +		writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg); +		goto sem_get; +	} + +	/* +	 * Clear fwver hdr +	 */ +	pgnum = PSS_SMEM_PGNUM(iocpf->ioc->ioc_regs.smem_pg0, loff); +	pgoff = PSS_SMEM_PGOFF(loff); +	writel(pgnum, iocpf->ioc->ioc_regs.host_page_num_fn); + +	for (i = 0; i < sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32); i++) { +		bfa_mem_write(iocpf->ioc->ioc_regs.smem_page_start, loff, 0); +		loff += sizeof(u32); +	} + +	bfa_trc(iocpf->ioc, fwstate); +	bfa_trc(iocpf->ioc, swab32(fwhdr.exec)); +	bfa_ioc_set_cur_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT); +	bfa_ioc_set_alt_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT); + +	/* +	 * Unlock the hw semaphore. Should be here only once per boot. +	 */ +	bfa_ioc_ownership_reset(iocpf->ioc); + +	/* +	 * unlock init semaphore. +	 */ +	writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg); + +sem_get:  	bfa_ioc_hw_sem_get(iocpf->ioc);  } @@ -668,22 +778,33 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	switch (event) {  	case IOCPF_E_SEMLOCKED:  		if (bfa_ioc_firmware_lock(ioc)) { -			iocpf->retry_count = 0; -			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); +			if (bfa_ioc_sync_start(ioc)) { +				bfa_ioc_sync_join(ioc); +				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); +			} else { +				bfa_ioc_firmware_unlock(ioc); +				writel(1, ioc->ioc_regs.ioc_sem_reg); +				bfa_sem_timer_start(ioc); +			}  		} else { -			bfa_ioc_hw_sem_release(ioc); +			writel(1, ioc->ioc_regs.ioc_sem_reg);  			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);  		}  		break; +	case IOCPF_E_SEM_ERROR: +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); +		bfa_fsm_send_event(ioc, IOC_E_HWFAILED); +		break; +  	case IOCPF_E_DISABLE: -		bfa_ioc_hw_sem_get_cancel(ioc); +		bfa_sem_timer_stop(ioc);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); -		bfa_ioc_pf_disabled(ioc); +		bfa_fsm_send_event(ioc, IOC_E_DISABLED);  		break;  	case IOCPF_E_STOP: -		bfa_ioc_hw_sem_get_cancel(ioc); +		bfa_sem_timer_stop(ioc);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);  		break; @@ -701,10 +822,10 @@ bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)  	/*  	 * Call only the first time sm enters fwmismatch state.  	 */ -	if (iocpf->retry_count == 0) +	if (iocpf->fw_mismatch_notified == BFA_FALSE)  		bfa_ioc_pf_fwmismatch(iocpf->ioc); -	iocpf->retry_count++; +	iocpf->fw_mismatch_notified = BFA_TRUE;  	bfa_iocpf_timer_start(iocpf->ioc);  } @@ -726,7 +847,7 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	case IOCPF_E_DISABLE:  		bfa_iocpf_timer_stop(ioc);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); -		bfa_ioc_pf_disabled(ioc); +		bfa_fsm_send_event(ioc, IOC_E_DISABLED);  		break;  	case IOCPF_E_STOP: @@ -760,13 +881,23 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	switch (event) {  	case IOCPF_E_SEMLOCKED: -		iocpf->retry_count = 0; -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); +		if (bfa_ioc_sync_complete(ioc)) { +			bfa_ioc_sync_join(ioc); +			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); +		} else { +			writel(1, ioc->ioc_regs.ioc_sem_reg); +			bfa_sem_timer_start(ioc); +		} +		break; + +	case IOCPF_E_SEM_ERROR: +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); +		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);  		break;  	case IOCPF_E_DISABLE: -		bfa_ioc_hw_sem_get_cancel(ioc); -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); +		bfa_sem_timer_stop(ioc); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);  		break;  	default: @@ -774,12 +905,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	}  } -  static void  bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)  { -	bfa_iocpf_timer_start(iocpf->ioc); -	bfa_ioc_reset(iocpf->ioc, BFA_FALSE); +	iocpf->poll_time = 0; +	bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);  }  /* @@ -795,34 +925,19 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	switch (event) {  	case IOCPF_E_FWREADY: -		bfa_iocpf_timer_stop(ioc);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);  		break; -	case IOCPF_E_INITFAIL: -		bfa_iocpf_timer_stop(ioc); -		/* -		 * !!! fall through !!! -		 */ -  	case IOCPF_E_TIMEOUT: -		iocpf->retry_count++; -		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) { -			bfa_iocpf_timer_start(ioc); -			bfa_ioc_reset(ioc, BFA_TRUE); -			break; -		} - -		bfa_ioc_hw_sem_release(ioc); -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - -		if (event == IOCPF_E_TIMEOUT) -			bfa_ioc_pf_failed(ioc); +		writel(1, ioc->ioc_regs.ioc_sem_reg); +		bfa_fsm_send_event(ioc, IOC_E_PFFAILED); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);  		break;  	case IOCPF_E_DISABLE: -		bfa_ioc_hw_sem_release(ioc);  		bfa_iocpf_timer_stop(ioc); +		bfa_ioc_sync_leave(ioc); +		writel(1, ioc->ioc_regs.ioc_sem_reg);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);  		break; @@ -831,11 +946,14 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	}  } -  static void  bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)  {  	bfa_iocpf_timer_start(iocpf->ioc); +	/* +	 * Enable Interrupts before sending fw IOC ENABLE cmd. +	 */ +	iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);  	bfa_ioc_send_enable(iocpf->ioc);  } @@ -853,7 +971,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	switch (event) {  	case IOCPF_E_FWRSP_ENABLE:  		bfa_iocpf_timer_stop(ioc); -		bfa_ioc_hw_sem_release(ioc); +		writel(1, ioc->ioc_regs.ioc_sem_reg);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);  		break; @@ -864,41 +982,27 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  		 */  	case IOCPF_E_TIMEOUT: -		iocpf->retry_count++; -		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) { -			writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); -			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); -			break; -		} - -		bfa_ioc_hw_sem_release(ioc); -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - +		writel(1, ioc->ioc_regs.ioc_sem_reg);  		if (event == IOCPF_E_TIMEOUT) -			bfa_ioc_pf_failed(ioc); +			bfa_fsm_send_event(ioc, IOC_E_PFFAILED); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);  		break;  	case IOCPF_E_DISABLE:  		bfa_iocpf_timer_stop(ioc); -		bfa_ioc_hw_sem_release(ioc); +		writel(1, ioc->ioc_regs.ioc_sem_reg);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);  		break; -	case IOCPF_E_FWREADY: -		bfa_ioc_send_enable(ioc); -		break; -  	default:  		bfa_sm_fault(ioc, event);  	}  } - -  static void  bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)  { -	bfa_ioc_pf_enabled(iocpf->ioc); +	bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);  }  static void @@ -914,20 +1018,11 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  		break;  	case IOCPF_E_GETATTRFAIL: -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);  		break;  	case IOCPF_E_FAIL: -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); -		break; - -	case IOCPF_E_FWREADY: -		if (bfa_ioc_is_operational(ioc)) -			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); -		else -			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - -		bfa_ioc_pf_failed(ioc); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);  		break;  	default: @@ -935,7 +1030,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	}  } -  static void  bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)  { @@ -955,9 +1049,8 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	switch (event) {  	case IOCPF_E_FWRSP_DISABLE: -	case IOCPF_E_FWREADY:  		bfa_iocpf_timer_stop(ioc); -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);  		break;  	case IOCPF_E_FAIL: @@ -967,8 +1060,8 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  		 */  	case IOCPF_E_TIMEOUT: -		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); +		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);  		break;  	case IOCPF_E_FWRSP_ENABLE: @@ -979,13 +1072,50 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	}  } +static void +bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf) +{ +	bfa_ioc_hw_sem_get(iocpf->ioc); +} + +/* + * IOC hb ack request is being removed. + */ +static void +bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) +{ +	struct bfa_ioc_s *ioc = iocpf->ioc; + +	bfa_trc(ioc, event); + +	switch (event) { +	case IOCPF_E_SEMLOCKED: +		bfa_ioc_sync_leave(ioc); +		writel(1, ioc->ioc_regs.ioc_sem_reg); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); +		break; + +	case IOCPF_E_SEM_ERROR: +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); +		bfa_fsm_send_event(ioc, IOC_E_HWFAILED); +		break; + +	case IOCPF_E_FAIL: +		break; + +	default: +		bfa_sm_fault(ioc, event); +	} +} +  /*   * IOC disable completion entry.   */  static void  bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)  { -	bfa_ioc_pf_disabled(iocpf->ioc); +	bfa_ioc_mbox_flush(iocpf->ioc); +	bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);  }  static void @@ -1010,11 +1140,60 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	}  } +static void +bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf) +{ +	bfa_ioc_debug_save_ftrc(iocpf->ioc); +	bfa_ioc_hw_sem_get(iocpf->ioc); +} + +/* + * Hardware initialization failed. + */ +static void +bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) +{ +	struct bfa_ioc_s *ioc = iocpf->ioc; + +	bfa_trc(ioc, event); + +	switch (event) { +	case IOCPF_E_SEMLOCKED: +		bfa_ioc_notify_fail(ioc); +		bfa_ioc_sync_leave(ioc); +		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); +		writel(1, ioc->ioc_regs.ioc_sem_reg); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); +		break; + +	case IOCPF_E_SEM_ERROR: +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); +		bfa_fsm_send_event(ioc, IOC_E_HWFAILED); +		break; + +	case IOCPF_E_DISABLE: +		bfa_sem_timer_stop(ioc); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); +		break; + +	case IOCPF_E_STOP: +		bfa_sem_timer_stop(ioc); +		bfa_ioc_firmware_unlock(ioc); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); +		break; + +	case IOCPF_E_FAIL: +		break; + +	default: +		bfa_sm_fault(ioc, event); +	} +}  static void  bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)  { -	bfa_iocpf_timer_start(iocpf->ioc); +	bfa_trc(iocpf->ioc, 0);  }  /* @@ -1029,47 +1208,83 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	switch (event) {  	case IOCPF_E_DISABLE: -		bfa_iocpf_timer_stop(ioc);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);  		break;  	case IOCPF_E_STOP: -		bfa_iocpf_timer_stop(ioc);  		bfa_ioc_firmware_unlock(ioc);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);  		break; -	case IOCPF_E_TIMEOUT: -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); -		break; -  	default:  		bfa_sm_fault(ioc, event);  	}  } -  static void -bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) +bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)  {  	/*  	 * Mark IOC as failed in hardware and stop firmware.  	 */  	bfa_ioc_lpu_stop(iocpf->ioc); -	writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate); - -	/* -	 * Notify other functions on HB failure. -	 */ -	bfa_ioc_notify_hbfail(iocpf->ioc);  	/*  	 * Flush any queued up mailbox requests.  	 */ -	bfa_ioc_mbox_hbfail(iocpf->ioc); +	bfa_ioc_mbox_flush(iocpf->ioc); + +	bfa_ioc_hw_sem_get(iocpf->ioc); +} + +static void +bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) +{ +	struct bfa_ioc_s *ioc = iocpf->ioc; + +	bfa_trc(ioc, event); + +	switch (event) { +	case IOCPF_E_SEMLOCKED: +		bfa_ioc_sync_ack(ioc); +		bfa_ioc_notify_fail(ioc); +		if (!iocpf->auto_recover) { +			bfa_ioc_sync_leave(ioc); +			bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); +			writel(1, ioc->ioc_regs.ioc_sem_reg); +			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); +		} else { +			if (bfa_ioc_sync_complete(ioc)) +				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); +			else { +				writel(1, ioc->ioc_regs.ioc_sem_reg); +				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); +			} +		} +		break; -	if (iocpf->auto_recover) -		bfa_iocpf_recovery_timer_start(iocpf->ioc); +	case IOCPF_E_SEM_ERROR: +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); +		bfa_fsm_send_event(ioc, IOC_E_HWFAILED); +		break; + +	case IOCPF_E_DISABLE: +		bfa_sem_timer_stop(ioc); +		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); +		break; + +	case IOCPF_E_FAIL: +		break; + +	default: +		bfa_sm_fault(ioc, event); +	} +} + +static void +bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) +{ +	bfa_trc(iocpf->ioc, 0);  }  /* @@ -1084,41 +1299,38 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)  	switch (event) {  	case IOCPF_E_DISABLE: -		if (iocpf->auto_recover) -			bfa_iocpf_timer_stop(ioc);  		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);  		break; -	case IOCPF_E_TIMEOUT: -		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); -		break; -  	default:  		bfa_sm_fault(ioc, event);  	}  } - +/* + *  BFA IOC private functions + */  /* - *  hal_ioc_pvt BFA IOC private functions + * Notify common modules registered for notification.   */ +static void +bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event) +{ +	struct bfa_ioc_notify_s	*notify; +	struct list_head	*qe; + +	list_for_each(qe, &ioc->notify_q) { +		notify = (struct bfa_ioc_notify_s *)qe; +		notify->cbfn(notify->cbarg, event); +	} +}  static void  bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)  { -	struct list_head			*qe; -	struct bfa_ioc_hbfail_notify_s	*notify; -  	ioc->cbfn->disable_cbfn(ioc->bfa); - -	/* -	 * Notify common modules registered for notification. -	 */ -	list_for_each(qe, &ioc->hb_notify_q) { -		notify = (struct bfa_ioc_hbfail_notify_s *) qe; -		notify->cbfn(notify->cbarg); -	} +	bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);  }  bfa_boolean_t @@ -1130,25 +1342,18 @@ bfa_ioc_sem_get(void __iomem *sem_reg)  	r32 = readl(sem_reg); -	while (r32 && (cnt < BFA_SEM_SPINCNT)) { +	while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {  		cnt++;  		udelay(2);  		r32 = readl(sem_reg);  	} -	if (r32 == 0) +	if (!(r32 & 1))  		return BFA_TRUE; -	bfa_assert(cnt < BFA_SEM_SPINCNT);  	return BFA_FALSE;  } -void -bfa_ioc_sem_release(void __iomem *sem_reg) -{ -	writel(1, sem_reg); -} -  static void  bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)  { @@ -1159,7 +1364,12 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)  	 * will return 1. Semaphore is released by writing 1 to the register  	 */  	r32 = readl(ioc->ioc_regs.ioc_sem_reg); -	if (r32 == 0) { +	if (r32 == ~0) { +		WARN_ON(r32 == ~0); +		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR); +		return; +	} +	if (!(r32 & 1)) {  		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);  		return;  	} @@ -1167,18 +1377,6 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)  	bfa_sem_timer_start(ioc);  } -void -bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc) -{ -	writel(1, ioc->ioc_regs.ioc_sem_reg); -} - -static void -bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc) -{ -	bfa_sem_timer_stop(ioc); -} -  /*   * Initialize LPU local memory (aka secondary memory / SRAM)   */ @@ -1212,7 +1410,7 @@ bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)  	 * If memory initialization is not successful, IOC timeout will catch  	 * such failures.  	 */ -	bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE); +	WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));  	bfa_trc(ioc, pss_ctl);  	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN); @@ -1258,8 +1456,8 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)  	int		i;  	u32	*fwsig = (u32 *) fwhdr; -	pgnum = bfa_ioc_smem_pgnum(ioc, loff); -	pgoff = bfa_ioc_smem_pgoff(ioc, loff); +	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); +	pgoff = PSS_SMEM_PGOFF(loff);  	writel(pgnum, ioc->ioc_regs.host_page_num_fn);  	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32)); @@ -1271,28 +1469,42 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)  }  /* - * Returns TRUE if same. + * Returns TRUE if driver is willing to work with current smem f/w version.   */  bfa_boolean_t -bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) +bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, +		struct bfi_ioc_image_hdr_s *smem_fwhdr)  {  	struct bfi_ioc_image_hdr_s *drv_fwhdr; -	int i; +	enum bfi_ioc_img_ver_cmp_e smem_flash_cmp, drv_smem_cmp;  	drv_fwhdr = (struct bfi_ioc_image_hdr_s *) -		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); +		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); -	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { -		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) { -			bfa_trc(ioc, i); -			bfa_trc(ioc, fwhdr->md5sum[i]); -			bfa_trc(ioc, drv_fwhdr->md5sum[i]); -			return BFA_FALSE; -		} +	/* +	 * If smem is incompatible or old, driver should not work with it. +	 */ +	drv_smem_cmp = bfa_ioc_fw_ver_patch_cmp(drv_fwhdr, smem_fwhdr); +	if (drv_smem_cmp == BFI_IOC_IMG_VER_INCOMP || +		drv_smem_cmp == BFI_IOC_IMG_VER_OLD) { +		return BFA_FALSE;  	} -	bfa_trc(ioc, fwhdr->md5sum[0]); -	return BFA_TRUE; +	/* +	 * IF Flash has a better F/W than smem do not work with smem. +	 * If smem f/w == flash f/w, as smem f/w not old | incmp, work with it. +	 * If Flash is old or incomp work with smem iff smem f/w == drv f/w. +	 */ +	smem_flash_cmp = bfa_ioc_flash_fwver_cmp(ioc, smem_fwhdr); + +	if (smem_flash_cmp == BFI_IOC_IMG_VER_BETTER) { +		return BFA_FALSE; +	} else if (smem_flash_cmp == BFI_IOC_IMG_VER_SAME) { +		return BFA_TRUE; +	} else { +		return (drv_smem_cmp == BFI_IOC_IMG_VER_SAME) ? +			BFA_TRUE : BFA_FALSE; +	}  }  /* @@ -1302,31 +1514,179 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)  static bfa_boolean_t  bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)  { -	struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr; - -	/* -	 * If bios/efi boot (flash based) -- return true -	 */ -	if (bfa_ioc_is_bios_optrom(ioc)) -		return BFA_TRUE; +	struct bfi_ioc_image_hdr_s fwhdr;  	bfa_ioc_fwver_get(ioc, &fwhdr); -	drv_fwhdr = (struct bfi_ioc_image_hdr_s *) -		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); -	if (fwhdr.signature != drv_fwhdr->signature) { -		bfa_trc(ioc, fwhdr.signature); -		bfa_trc(ioc, drv_fwhdr->signature); +	if (swab32(fwhdr.bootenv) != boot_env) { +		bfa_trc(ioc, fwhdr.bootenv); +		bfa_trc(ioc, boot_env);  		return BFA_FALSE;  	} -	if (swab32(fwhdr.param) != boot_env) { -		bfa_trc(ioc, fwhdr.param); -		bfa_trc(ioc, boot_env); +	return bfa_ioc_fwver_cmp(ioc, &fwhdr); +} + +static bfa_boolean_t +bfa_ioc_fwver_md5_check(struct bfi_ioc_image_hdr_s *fwhdr_1, +				struct bfi_ioc_image_hdr_s *fwhdr_2) +{ +	int i; + +	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) +		if (fwhdr_1->md5sum[i] != fwhdr_2->md5sum[i]) +			return BFA_FALSE; + +	return BFA_TRUE; +} + +/* + * Returns TRUE if major minor and maintainence are same. + * If patch versions are same, check for MD5 Checksum to be same. + */ +static bfa_boolean_t +bfa_ioc_fw_ver_compatible(struct bfi_ioc_image_hdr_s *drv_fwhdr, +				struct bfi_ioc_image_hdr_s *fwhdr_to_cmp) +{ +	if (drv_fwhdr->signature != fwhdr_to_cmp->signature) +		return BFA_FALSE; + +	if (drv_fwhdr->fwver.major != fwhdr_to_cmp->fwver.major) +		return BFA_FALSE; + +	if (drv_fwhdr->fwver.minor != fwhdr_to_cmp->fwver.minor) +		return BFA_FALSE; + +	if (drv_fwhdr->fwver.maint != fwhdr_to_cmp->fwver.maint)  		return BFA_FALSE; + +	if (drv_fwhdr->fwver.patch == fwhdr_to_cmp->fwver.patch && +		drv_fwhdr->fwver.phase == fwhdr_to_cmp->fwver.phase && +		drv_fwhdr->fwver.build == fwhdr_to_cmp->fwver.build) { +		return bfa_ioc_fwver_md5_check(drv_fwhdr, fwhdr_to_cmp);  	} -	return bfa_ioc_fwver_cmp(ioc, &fwhdr); +	return BFA_TRUE; +} + +static bfa_boolean_t +bfa_ioc_flash_fwver_valid(struct bfi_ioc_image_hdr_s *flash_fwhdr) +{ +	if (flash_fwhdr->fwver.major == 0 || flash_fwhdr->fwver.major == 0xFF) +		return BFA_FALSE; + +	return BFA_TRUE; +} + +static bfa_boolean_t fwhdr_is_ga(struct bfi_ioc_image_hdr_s *fwhdr) +{ +	if (fwhdr->fwver.phase == 0 && +		fwhdr->fwver.build == 0) +		return BFA_TRUE; + +	return BFA_FALSE; +} + +/* + * Returns TRUE if both are compatible and patch of fwhdr_to_cmp is better. + */ +static enum bfi_ioc_img_ver_cmp_e +bfa_ioc_fw_ver_patch_cmp(struct bfi_ioc_image_hdr_s *base_fwhdr, +				struct bfi_ioc_image_hdr_s *fwhdr_to_cmp) +{ +	if (bfa_ioc_fw_ver_compatible(base_fwhdr, fwhdr_to_cmp) == BFA_FALSE) +		return BFI_IOC_IMG_VER_INCOMP; + +	if (fwhdr_to_cmp->fwver.patch > base_fwhdr->fwver.patch) +		return BFI_IOC_IMG_VER_BETTER; + +	else if (fwhdr_to_cmp->fwver.patch < base_fwhdr->fwver.patch) +		return BFI_IOC_IMG_VER_OLD; + +	/* +	 * GA takes priority over internal builds of the same patch stream. +	 * At this point major minor maint and patch numbers are same. +	 */ + +	if (fwhdr_is_ga(base_fwhdr) == BFA_TRUE) { +		if (fwhdr_is_ga(fwhdr_to_cmp)) +			return BFI_IOC_IMG_VER_SAME; +		else +			return BFI_IOC_IMG_VER_OLD; +	} else { +		if (fwhdr_is_ga(fwhdr_to_cmp)) +			return BFI_IOC_IMG_VER_BETTER; +	} + +	if (fwhdr_to_cmp->fwver.phase > base_fwhdr->fwver.phase) +		return BFI_IOC_IMG_VER_BETTER; +	else if (fwhdr_to_cmp->fwver.phase < base_fwhdr->fwver.phase) +		return BFI_IOC_IMG_VER_OLD; + +	if (fwhdr_to_cmp->fwver.build > base_fwhdr->fwver.build) +		return BFI_IOC_IMG_VER_BETTER; +	else if (fwhdr_to_cmp->fwver.build < base_fwhdr->fwver.build) +		return BFI_IOC_IMG_VER_OLD; + +	/* +	 * All Version Numbers are equal. +	 * Md5 check to be done as a part of compatibility check. +	 */ +	return BFI_IOC_IMG_VER_SAME; +} + +#define BFA_FLASH_PART_FWIMG_ADDR	0x100000 /* fw image address */ + +bfa_status_t +bfa_ioc_flash_img_get_chnk(struct bfa_ioc_s *ioc, u32 off, +				u32 *fwimg) +{ +	return bfa_flash_raw_read(ioc->pcidev.pci_bar_kva, +			BFA_FLASH_PART_FWIMG_ADDR + (off * sizeof(u32)), +			(char *)fwimg, BFI_FLASH_CHUNK_SZ); +} + +static enum bfi_ioc_img_ver_cmp_e +bfa_ioc_flash_fwver_cmp(struct bfa_ioc_s *ioc, +			struct bfi_ioc_image_hdr_s *base_fwhdr) +{ +	struct bfi_ioc_image_hdr_s *flash_fwhdr; +	bfa_status_t status; +	u32 fwimg[BFI_FLASH_CHUNK_SZ_WORDS]; + +	status = bfa_ioc_flash_img_get_chnk(ioc, 0, fwimg); +	if (status != BFA_STATUS_OK) +		return BFI_IOC_IMG_VER_INCOMP; + +	flash_fwhdr = (struct bfi_ioc_image_hdr_s *) fwimg; +	if (bfa_ioc_flash_fwver_valid(flash_fwhdr) == BFA_TRUE) +		return bfa_ioc_fw_ver_patch_cmp(base_fwhdr, flash_fwhdr); +	else +		return BFI_IOC_IMG_VER_INCOMP; +} + + +/* + * Invalidate fwver signature + */ +bfa_status_t +bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc) +{ + +	u32	pgnum, pgoff; +	u32	loff = 0; +	enum bfi_ioc_state ioc_fwstate; + +	ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc); +	if (!bfa_ioc_state_disabled(ioc_fwstate)) +		return BFA_STATUS_ADAPTER_ENABLED; + +	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); +	pgoff = PSS_SMEM_PGOFF(loff); +	writel(pgnum, ioc->ioc_regs.host_page_num_fn); +	bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, BFA_IOC_FW_INV_SIGN); + +	return BFA_STATUS_OK;  }  /* @@ -1342,7 +1702,6 @@ bfa_ioc_msgflush(struct bfa_ioc_s *ioc)  		writel(1, ioc->ioc_regs.lpu_mbox_cmd);  } -  static void  bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)  { @@ -1351,31 +1710,15 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)  	u32 boot_type;  	u32 boot_env; -	ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); +	ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);  	if (force)  		ioc_fwstate = BFI_IOC_UNINIT;  	bfa_trc(ioc, ioc_fwstate); -	boot_type = BFI_BOOT_TYPE_NORMAL; -	boot_env = BFI_BOOT_LOADER_OS; - -	/* -	 * Flash based firmware boot BIOS env. -	 */ -	if (bfa_ioc_is_bios_optrom(ioc)) { -		boot_type = BFI_BOOT_TYPE_FLASH; -		boot_env = BFI_BOOT_LOADER_BIOS; -	} - -	/* -	 * Flash based firmware boot UEFI env. -	 */ -	if (bfa_ioc_is_uefi(ioc)) { -		boot_type = BFI_BOOT_TYPE_FLASH; -		boot_env = BFI_BOOT_LOADER_UEFI; -	} +	boot_type = BFI_FWBOOT_TYPE_NORMAL; +	boot_env = BFI_FWBOOT_ENV_OS;  	/*  	 * check if firmware is valid @@ -1384,7 +1727,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)  		BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);  	if (!fwvalid) { -		bfa_ioc_boot(ioc, boot_type, boot_env); +		if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK) +			bfa_ioc_poll_fwinit(ioc);  		return;  	} @@ -1393,7 +1737,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)  	 * just wait for an initialization completion interrupt.  	 */  	if (ioc_fwstate == BFI_IOC_INITING) { -		ioc->cbfn->reset_cbfn(ioc->bfa); +		bfa_ioc_poll_fwinit(ioc);  		return;  	} @@ -1405,15 +1749,13 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)  	 * convergence, IOC will be in operational state when 2nd driver  	 * is loaded.  	 */ -	if (ioc_fwstate == BFI_IOC_DISABLED || -	    (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) { +	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {  		/*  		 * When using MSI-X any pending firmware ready event should  		 * be flushed. Otherwise MSI-X interrupts are not delivered.  		 */  		bfa_ioc_msgflush(ioc); -		ioc->cbfn->reset_cbfn(ioc->bfa);  		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);  		return;  	} @@ -1421,7 +1763,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)  	/*  	 * Initialize the h/w for any other states.  	 */ -	bfa_ioc_boot(ioc, boot_type, boot_env); +	if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK) +		bfa_ioc_poll_fwinit(ioc);  }  static void @@ -1442,7 +1785,7 @@ bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)  	bfa_trc(ioc, msgp[0]);  	bfa_trc(ioc, len); -	bfa_assert(len <= BFI_IOC_MSGLEN_MAX); +	WARN_ON(len > BFI_IOC_MSGLEN_MAX);  	/*  	 * first write msg to mailbox registers @@ -1465,12 +1808,12 @@ static void  bfa_ioc_send_enable(struct bfa_ioc_s *ioc)  {  	struct bfi_ioc_ctrl_req_s enable_req; -	struct bfa_timeval_s tv; +	struct timeval tv;  	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,  		    bfa_ioc_portid(ioc)); -	enable_req.ioc_class = ioc->ioc_mc; -	bfa_os_gettimeofday(&tv); +	enable_req.clscode = cpu_to_be16(ioc->clscode); +	do_gettimeofday(&tv);  	enable_req.tv_sec = be32_to_cpu(tv.tv_sec);  	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));  } @@ -1504,7 +1847,6 @@ bfa_ioc_hb_check(void *cbarg)  	hb_count = readl(ioc->ioc_regs.heartbeat);  	if (ioc->hb_count == hb_count) { -		printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);  		bfa_ioc_recover(ioc);  		return;  	} else { @@ -1522,17 +1864,10 @@ bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)  	bfa_hb_timer_start(ioc);  } -static void -bfa_ioc_hb_stop(struct bfa_ioc_s *ioc) -{ -	bfa_hb_timer_stop(ioc); -} - -  /*   *	Initiate a full firmware download.   */ -static void +static bfa_status_t  bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,  		    u32 boot_env)  { @@ -1541,26 +1876,54 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,  	u32 loff = 0;  	u32 chunkno = 0;  	u32 i; +	u32 asicmode; +	u32 fwimg_size; +	u32 fwimg_buf[BFI_FLASH_CHUNK_SZ_WORDS]; +	bfa_status_t status; -	/* -	 * Initialize LMEM first before code download -	 */ -	bfa_ioc_lmem_init(ioc); +	if (boot_env == BFI_FWBOOT_ENV_OS && +		boot_type == BFI_FWBOOT_TYPE_FLASH) { +		fwimg_size = BFI_FLASH_IMAGE_SZ/sizeof(u32); -	bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc))); -	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno); +		status = bfa_ioc_flash_img_get_chnk(ioc, +			BFA_IOC_FLASH_CHUNK_ADDR(chunkno), fwimg_buf); +		if (status != BFA_STATUS_OK) +			return status; -	pgnum = bfa_ioc_smem_pgnum(ioc, loff); -	pgoff = bfa_ioc_smem_pgoff(ioc, loff); +		fwimg = fwimg_buf; +	} else { +		fwimg_size = bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); +		fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), +					BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); +	} + +	bfa_trc(ioc, fwimg_size); + + +	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); +	pgoff = PSS_SMEM_PGOFF(loff);  	writel(pgnum, ioc->ioc_regs.host_page_num_fn); -	for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) { +	for (i = 0; i < fwimg_size; i++) {  		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {  			chunkno = BFA_IOC_FLASH_CHUNK_NO(i); -			fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), + +			if (boot_env == BFI_FWBOOT_ENV_OS && +				boot_type == BFI_FWBOOT_TYPE_FLASH) { +				status = bfa_ioc_flash_img_get_chnk(ioc, +					BFA_IOC_FLASH_CHUNK_ADDR(chunkno), +					fwimg_buf); +				if (status != BFA_STATUS_OK) +					return status; + +				fwimg = fwimg_buf; +			} else { +				fwimg = bfa_cb_image_get_chunk( +					bfa_ioc_asic_gen(ioc),  					BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); +			}  		}  		/* @@ -1581,22 +1944,27 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,  		}  	} -	writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn); +	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0), +			ioc->ioc_regs.host_page_num_fn);  	/* -	 * Set boot type and boot param at the end. -	*/ -	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF, +	 * Set boot type, env and device mode at the end. +	 */ +	if (boot_env == BFI_FWBOOT_ENV_OS && +		boot_type == BFI_FWBOOT_TYPE_FLASH) { +		boot_type = BFI_FWBOOT_TYPE_NORMAL; +	} +	asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode, +				ioc->port0_mode, ioc->port1_mode); +	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF, +			swab32(asicmode)); +	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,  			swab32(boot_type)); -	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF, +	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,  			swab32(boot_env)); +	return BFA_STATUS_OK;  } -static void -bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force) -{ -	bfa_ioc_hwinit(ioc, force); -}  /*   * Update BFA configuration from firmware configuration. @@ -1609,6 +1977,8 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)  	attr->adapter_prop  = be32_to_cpu(attr->adapter_prop);  	attr->card_type     = be32_to_cpu(attr->card_type);  	attr->maxfrsize	    = be16_to_cpu(attr->maxfrsize); +	ioc->fcmode	= (attr->port_mode == BFI_PORT_MODE_FC); +	attr->mfg_year	= be16_to_cpu(attr->mfg_year);  	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);  } @@ -1663,7 +2033,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)   * Cleanup any pending requests.   */  static void -bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc) +bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)  {  	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;  	struct bfa_mbox_cmd_s		*cmd; @@ -1683,12 +2053,13 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)  static bfa_status_t  bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)  { -	u32 pgnum, loff, r32; +	u32 pgnum, loff; +	__be32 r32;  	int i, len;  	u32 *buf = tbuf; -	pgnum = bfa_ioc_smem_pgnum(ioc, soff); -	loff = bfa_ioc_smem_pgoff(ioc, soff); +	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff); +	loff = PSS_SMEM_PGOFF(soff);  	bfa_trc(ioc, pgnum);  	bfa_trc(ioc, loff);  	bfa_trc(ioc, sz); @@ -1707,7 +2078,7 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)  	bfa_trc(ioc, len);  	for (i = 0; i < len; i++) {  		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff); -		buf[i] = be32_to_cpu(r32); +		buf[i] = swab32(r32);  		loff += sizeof(u32);  		/* @@ -1719,11 +2090,13 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)  			writel(pgnum, ioc->ioc_regs.host_page_num_fn);  		}  	} -	writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn); +	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0), +			ioc->ioc_regs.host_page_num_fn);  	/*  	 *  release semaphore.  	 */ -	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); +	readl(ioc->ioc_regs.ioc_init_sem_reg); +	writel(1, ioc->ioc_regs.ioc_init_sem_reg);  	bfa_trc(ioc, pgnum);  	return BFA_STATUS_OK; @@ -1742,8 +2115,8 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)  	int i, len;  	u32 pgnum, loff; -	pgnum = bfa_ioc_smem_pgnum(ioc, soff); -	loff = bfa_ioc_smem_pgoff(ioc, soff); +	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff); +	loff = PSS_SMEM_PGOFF(soff);  	bfa_trc(ioc, pgnum);  	bfa_trc(ioc, loff);  	bfa_trc(ioc, sz); @@ -1773,35 +2146,35 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)  			writel(pgnum, ioc->ioc_regs.host_page_num_fn);  		}  	} -	writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn); +	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0), +			ioc->ioc_regs.host_page_num_fn);  	/*  	 *  release semaphore.  	 */ -	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); +	readl(ioc->ioc_regs.ioc_init_sem_reg); +	writel(1, ioc->ioc_regs.ioc_init_sem_reg);  	bfa_trc(ioc, pgnum);  	return BFA_STATUS_OK;  } -/* - * hal iocpf to ioc interface - */  static void -bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc) +bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)  { -	bfa_fsm_send_event(ioc, IOC_E_ENABLED); -} +	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; -static void -bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc) -{ -	bfa_fsm_send_event(ioc, IOC_E_DISABLED); -} +	/* +	 * Notify driver and common modules registered for notification. +	 */ +	ioc->cbfn->hbfail_cbfn(ioc->bfa); +	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED); + +	bfa_ioc_debug_save_ftrc(ioc); + +	BFA_LOG(KERN_CRIT, bfad, bfa_log_level, +		"Heart Beat of IOC has failed\n"); +	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL); -static void -bfa_ioc_pf_failed(struct bfa_ioc_s *ioc) -{ -	bfa_fsm_send_event(ioc, IOC_E_FAILED);  }  static void @@ -1812,17 +2185,12 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)  	 * Provide enable completion callback.  	 */  	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); -	BFA_LOG(KERN_WARNING, bfad, log_level, +	BFA_LOG(KERN_WARNING, bfad, bfa_log_level,  		"Running firmware version is incompatible "  		"with the driver version\n"); +	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);  } - - -/* - *  hal_ioc_public - */ -  bfa_status_t  bfa_ioc_pll_init(struct bfa_ioc_s *ioc)  { @@ -1835,10 +2203,17 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)  	bfa_ioc_pll_init_asic(ioc);  	ioc->pllinit = BFA_TRUE; + +	/* +	 * Initialize LMEM +	 */ +	bfa_ioc_lmem_init(ioc); +  	/*  	 *  release semaphore.  	 */ -	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); +	readl(ioc->ioc_regs.ioc_init_sem_reg); +	writel(1, ioc->ioc_regs.ioc_init_sem_reg);  	return BFA_STATUS_OK;  } @@ -1847,36 +2222,51 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)   * Interface used by diag module to do firmware boot with memory test   * as the entry vector.   */ -void +bfa_status_t  bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)  { -	void __iomem *rb; - +	struct bfi_ioc_image_hdr_s *drv_fwhdr; +	bfa_status_t status;  	bfa_ioc_stats(ioc, ioc_boots);  	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK) -		return; +		return BFA_STATUS_FAILED; + +	if (boot_env == BFI_FWBOOT_ENV_OS && +		boot_type == BFI_FWBOOT_TYPE_NORMAL) { + +		drv_fwhdr = (struct bfi_ioc_image_hdr_s *) +			bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); + +		/* +		 * Work with Flash iff flash f/w is better than driver f/w. +		 * Otherwise push drivers firmware. +		 */ +		if (bfa_ioc_flash_fwver_cmp(ioc, drv_fwhdr) == +						BFI_IOC_IMG_VER_BETTER) +			boot_type = BFI_FWBOOT_TYPE_FLASH; +	}  	/*  	 * Initialize IOC state of all functions on a chip reset.  	 */ -	rb = ioc->pcidev.pci_bar_kva; -	if (boot_type == BFI_BOOT_TYPE_MEMTEST) { -		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG)); -		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG)); +	if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) { +		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_MEMTEST); +		bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_MEMTEST);  	} else { -		writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG)); -		writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG)); +		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_INITING); +		bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_INITING);  	}  	bfa_ioc_msgflush(ioc); -	bfa_ioc_download_fw(ioc, boot_type, boot_env); - -	/* -	 * Enable interrupts just before starting LPU -	 */ -	ioc->cbfn->reset_cbfn(ioc->bfa); -	bfa_ioc_lpu_start(ioc); +	status = bfa_ioc_download_fw(ioc, boot_type, boot_env); +	if (status == BFA_STATUS_OK) +		bfa_ioc_lpu_start(ioc); +	else { +		WARN_ON(boot_type == BFI_FWBOOT_TYPE_MEMTEST); +		bfa_iocpf_timeout(ioc); +	} +	return status;  }  /* @@ -1899,20 +2289,24 @@ bfa_ioc_is_operational(struct bfa_ioc_s *ioc)  bfa_boolean_t  bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)  { -	u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); +	u32 r32 = bfa_ioc_get_cur_ioc_fwstate(ioc);  	return ((r32 != BFI_IOC_UNINIT) &&  		(r32 != BFI_IOC_INITING) &&  		(r32 != BFI_IOC_MEMTEST));  } -void +bfa_boolean_t  bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)  { -	u32	*msgp = mbmsg; +	__be32	*msgp = mbmsg;  	u32	r32;  	int		i; +	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd); +	if ((r32 & 1) == 0) +		return BFA_FALSE; +  	/*  	 * read the MBOX msg  	 */ @@ -1928,6 +2322,8 @@ bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)  	 */  	writel(1, ioc->ioc_regs.lpu_mbox_cmd);  	readl(ioc->ioc_regs.lpu_mbox_cmd); + +	return BFA_TRUE;  }  void @@ -1944,11 +2340,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)  	case BFI_IOC_I2H_HBEAT:  		break; -	case BFI_IOC_I2H_READY_EVENT: -		bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY); -		break; -  	case BFI_IOC_I2H_ENABLE_REPLY: +		ioc->port_mode = ioc->port_mode_cfg = +				(enum bfa_mode_s)msg->fw_event.port_mode; +		ioc->ad_cap_bm = msg->fw_event.cap_bm;  		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);  		break; @@ -1962,7 +2357,7 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)  	default:  		bfa_trc(ioc, msg->mh.msg_id); -		bfa_assert(0); +		WARN_ON(1);  	}  } @@ -1985,7 +2380,7 @@ bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,  	ioc->iocpf.ioc	= ioc;  	bfa_ioc_mbox_attach(ioc); -	INIT_LIST_HEAD(&ioc->hb_notify_q); +	INIT_LIST_HEAD(&ioc->notify_q);  	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);  	bfa_fsm_send_event(ioc, IOC_E_RESET); @@ -1998,6 +2393,7 @@ void  bfa_ioc_detach(struct bfa_ioc_s *ioc)  {  	bfa_fsm_send_event(ioc, IOC_E_DETACH); +	INIT_LIST_HEAD(&ioc->notify_q);  }  /* @@ -2007,20 +2403,81 @@ bfa_ioc_detach(struct bfa_ioc_s *ioc)   */  void  bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, -		 enum bfi_mclass mc) +		enum bfi_pcifn_class clscode)  { -	ioc->ioc_mc	= mc; +	ioc->clscode	= clscode;  	ioc->pcidev	= *pcidev; -	ioc->ctdev	= bfa_asic_id_ct(ioc->pcidev.device_id); -	ioc->cna	= ioc->ctdev && !ioc->fcmode; + +	/* +	 * Initialize IOC and device personality +	 */ +	ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC; +	ioc->asic_mode  = BFI_ASIC_MODE_FC; + +	switch (pcidev->device_id) { +	case BFA_PCI_DEVICE_ID_FC_8G1P: +	case BFA_PCI_DEVICE_ID_FC_8G2P: +		ioc->asic_gen = BFI_ASIC_GEN_CB; +		ioc->fcmode = BFA_TRUE; +		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA; +		ioc->ad_cap_bm = BFA_CM_HBA; +		break; + +	case BFA_PCI_DEVICE_ID_CT: +		ioc->asic_gen = BFI_ASIC_GEN_CT; +		ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH; +		ioc->asic_mode  = BFI_ASIC_MODE_ETH; +		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA; +		ioc->ad_cap_bm = BFA_CM_CNA; +		break; + +	case BFA_PCI_DEVICE_ID_CT_FC: +		ioc->asic_gen = BFI_ASIC_GEN_CT; +		ioc->fcmode = BFA_TRUE; +		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA; +		ioc->ad_cap_bm = BFA_CM_HBA; +		break; + +	case BFA_PCI_DEVICE_ID_CT2: +	case BFA_PCI_DEVICE_ID_CT2_QUAD: +		ioc->asic_gen = BFI_ASIC_GEN_CT2; +		if (clscode == BFI_PCIFN_CLASS_FC && +		    pcidev->ssid == BFA_PCI_CT2_SSID_FC) { +			ioc->asic_mode  = BFI_ASIC_MODE_FC16; +			ioc->fcmode = BFA_TRUE; +			ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA; +			ioc->ad_cap_bm = BFA_CM_HBA; +		} else { +			ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH; +			ioc->asic_mode  = BFI_ASIC_MODE_ETH; +			if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) { +				ioc->port_mode = +				ioc->port_mode_cfg = BFA_MODE_CNA; +				ioc->ad_cap_bm = BFA_CM_CNA; +			} else { +				ioc->port_mode = +				ioc->port_mode_cfg = BFA_MODE_NIC; +				ioc->ad_cap_bm = BFA_CM_NIC; +			} +		} +		break; + +	default: +		WARN_ON(1); +	}  	/*  	 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c  	 */ -	if (ioc->ctdev) -		bfa_ioc_set_ct_hwif(ioc); -	else +	if (ioc->asic_gen == BFI_ASIC_GEN_CB)  		bfa_ioc_set_cb_hwif(ioc); +	else if (ioc->asic_gen == BFI_ASIC_GEN_CT) +		bfa_ioc_set_ct_hwif(ioc); +	else { +		WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2); +		bfa_ioc_set_ct2_hwif(ioc); +		bfa_ioc_ct2_poweron(ioc); +	}  	bfa_ioc_map_port(ioc);  	bfa_ioc_reg_init(ioc); @@ -2043,15 +2500,6 @@ bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa)  	ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;  } -/* - * Return size of dma memory required. - */ -u32 -bfa_ioc_meminfo(void) -{ -	return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ); -} -  void  bfa_ioc_enable(struct bfa_ioc_s *ioc)  { @@ -2068,17 +2516,11 @@ bfa_ioc_disable(struct bfa_ioc_s *ioc)  	bfa_fsm_send_event(ioc, IOC_E_DISABLE);  } -/* - * Returns memory required for saving firmware trace in case of crash. - * Driver must call this interface to allocate memory required for - * automatic saving of firmware trace. Driver should call - * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this - * trace memory. - */ -int -bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover) +void +bfa_ioc_suspend(struct bfa_ioc_s *ioc)  { -	return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0; +	ioc->dbg_fwsave_once = BFA_TRUE; +	bfa_fsm_send_event(ioc, IOC_E_HWERROR);  }  /* @@ -2089,19 +2531,7 @@ void  bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)  {  	ioc->dbg_fwsave	    = dbg_fwsave; -	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover); -} - -u32 -bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr) -{ -	return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr); -} - -u32 -bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr) -{ -	return PSS_SMEM_PGOFF(fmaddr); +	ioc->dbg_fwsave_len = BFA_DBG_FWTRC_LEN;  }  /* @@ -2179,36 +2609,38 @@ bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)  	struct bfi_mbmsg_s		m;  	int				mc; -	bfa_ioc_msgget(ioc, &m); +	if (bfa_ioc_msgget(ioc, &m)) { +		/* +		 * Treat IOC message class as special. +		 */ +		mc = m.mh.msg_class; +		if (mc == BFI_MC_IOC) { +			bfa_ioc_isr(ioc, &m); +			return; +		} + +		if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL)) +			return; -	/* -	 * Treat IOC message class as special. -	 */ -	mc = m.mh.msg_class; -	if (mc == BFI_MC_IOC) { -		bfa_ioc_isr(ioc, &m); -		return; +		mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);  	} -	if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL)) -		return; +	bfa_ioc_lpu_read_stat(ioc); -	mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m); +	/* +	 * Try to send pending mailbox commands +	 */ +	bfa_ioc_mbox_poll(ioc);  }  void  bfa_ioc_error_isr(struct bfa_ioc_s *ioc)  { +	bfa_ioc_stats(ioc, ioc_hbfails); +	ioc->stats.hb_count = ioc->hb_count;  	bfa_fsm_send_event(ioc, IOC_E_HWERROR);  } -void -bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc) -{ -	ioc->fcmode  = BFA_TRUE; -	ioc->port_id = bfa_ioc_pcifn(ioc); -} -  /*   * return true if IOC is disabled   */ @@ -2230,14 +2662,6 @@ bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)  		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);  } -#define bfa_ioc_state_disabled(__sm)		\ -	(((__sm) == BFI_IOC_UNINIT) ||		\ -	 ((__sm) == BFI_IOC_INITING) ||		\ -	 ((__sm) == BFI_IOC_HWINIT) ||		\ -	 ((__sm) == BFI_IOC_DISABLED) ||	\ -	 ((__sm) == BFI_IOC_FAIL) ||		\ -	 ((__sm) == BFI_IOC_CFG_DISABLED)) -  /*   * Check if adapter is disabled -- both IOCs should be in a disabled   * state. @@ -2246,17 +2670,16 @@ bfa_boolean_t  bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)  {  	u32	ioc_state; -	void __iomem *rb = ioc->pcidev.pci_bar_kva;  	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))  		return BFA_FALSE; -	ioc_state = readl(rb + BFA_IOC0_STATE_REG); +	ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);  	if (!bfa_ioc_state_disabled(ioc_state))  		return BFA_FALSE;  	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) { -		ioc_state = readl(rb + BFA_IOC1_STATE_REG); +		ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);  		if (!bfa_ioc_state_disabled(ioc_state))  			return BFA_FALSE;  	} @@ -2265,14 +2688,13 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)  }  /* - * Add to IOC heartbeat failure notification queue. To be used by common - * modules such as cee, port, diag. + * Reset IOC fwstate registers.   */  void -bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc, -			struct bfa_ioc_hbfail_notify_s *notify) +bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)  { -	list_add_tail(¬ify->qe, &ioc->hb_notify_q); +	bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_UNINIT); +	bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_UNINIT);  }  #define BFA_MFG_NAME "Brocade" @@ -2306,7 +2728,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,  	else  		ad_attr->prototype = 0; -	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc); +	ad_attr->pwwn = ioc->attr->pwwn;  	ad_attr->mac  = bfa_ioc_get_mac(ioc);  	ad_attr->pcie_gen = ioc_attr->pcie_gen; @@ -2316,23 +2738,25 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,  	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); -	ad_attr->cna_capable = ioc->cna; -	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna; +	ad_attr->cna_capable = bfa_ioc_is_cna(ioc); +	ad_attr->trunk_capable = (ad_attr->nports > 1) && +				  !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz; +	ad_attr->mfg_day = ioc_attr->mfg_day; +	ad_attr->mfg_month = ioc_attr->mfg_month; +	ad_attr->mfg_year = ioc_attr->mfg_year; +	memcpy(ad_attr->uuid, ioc_attr->uuid, BFA_ADAPTER_UUID_LEN);  }  enum bfa_ioc_type_e  bfa_ioc_get_type(struct bfa_ioc_s *ioc)  { -	if (!ioc->ctdev || ioc->fcmode) -		return BFA_IOC_TYPE_FC; -	else if (ioc->ioc_mc == BFI_MC_IOCFC) -		return BFA_IOC_TYPE_FCoE; -	else if (ioc->ioc_mc == BFI_MC_LL) -		return BFA_IOC_TYPE_LL; -	else { -		bfa_assert(ioc->ioc_mc == BFI_MC_LL); +	if (ioc->clscode == BFI_PCIFN_CLASS_ETH)  		return BFA_IOC_TYPE_LL; -	} + +	WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC); + +	return (ioc->attr->port_mode == BFI_PORT_MODE_FC) +		? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;  }  void @@ -2354,7 +2778,7 @@ bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)  void  bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)  { -	bfa_assert(chip_rev); +	WARN_ON(!chip_rev);  	memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN); @@ -2385,17 +2809,20 @@ void  bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)  {  	struct bfi_ioc_attr_s	*ioc_attr; +	u8 nports = bfa_ioc_get_nports(ioc); -	bfa_assert(model); +	WARN_ON(!model);  	memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);  	ioc_attr = ioc->attr; -	/* -	 * model name -	 */ -	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u", -		BFA_MFG_NAME, ioc_attr->card_type); +	if (bfa_asic_id_ct2(ioc->pcidev.device_id) && +		(!bfa_mfg_is_mezz(ioc_attr->card_type))) +		snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u-%u%s", +			BFA_MFG_NAME, ioc_attr->card_type, nports, "p"); +	else +		snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u", +			BFA_MFG_NAME, ioc_attr->card_type);  }  enum bfa_ioc_state @@ -2444,38 +2871,21 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)  	memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));  	ioc_attr->state = bfa_ioc_get_state(ioc); -	ioc_attr->port_id = ioc->port_id; +	ioc_attr->port_id = bfa_ioc_portid(ioc); +	ioc_attr->port_mode = ioc->port_mode; +	ioc_attr->port_mode_cfg = ioc->port_mode_cfg; +	ioc_attr->cap_bm = ioc->ad_cap_bm;  	ioc_attr->ioc_type = bfa_ioc_get_type(ioc);  	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr); -	ioc_attr->pci_attr.device_id = ioc->pcidev.device_id; -	ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func; +	ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc); +	ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc); +	ioc_attr->def_fn = (bfa_ioc_pcifn(ioc) == bfa_ioc_portid(ioc));  	bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);  } -/* - *  hal_wwn_public - */ -wwn_t -bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc) -{ -	return ioc->attr->pwwn; -} - -wwn_t -bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc) -{ -	return ioc->attr->nwwn; -} - -u64 -bfa_ioc_get_adid(struct bfa_ioc_s *ioc) -{ -	return ioc->attr->mfg_pwwn; -} -  mac_t  bfa_ioc_get_mac(struct bfa_ioc_s *ioc)  { @@ -2488,18 +2898,6 @@ bfa_ioc_get_mac(struct bfa_ioc_s *ioc)  		return ioc->attr->mac;  } -wwn_t -bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc) -{ -	return ioc->attr->mfg_pwwn; -} - -wwn_t -bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc) -{ -	return ioc->attr->mfg_nwwn; -} -  mac_t  bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)  { @@ -2515,10 +2913,41 @@ bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)  	return m;  } -bfa_boolean_t -bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc) +/* + * Send AEN notification + */ +void +bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)  { -	return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id); +	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; +	struct bfa_aen_entry_s	*aen_entry; +	enum bfa_ioc_type_e ioc_type; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	ioc_type = bfa_ioc_get_type(ioc); +	switch (ioc_type) { +	case BFA_IOC_TYPE_FC: +		aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn; +		break; +	case BFA_IOC_TYPE_FCoE: +		aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn; +		aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc); +		break; +	case BFA_IOC_TYPE_LL: +		aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc); +		break; +	default: +		WARN_ON(ioc_type != BFA_IOC_TYPE_FC); +		break; +	} + +	/* Send the AEN notification */ +	aen_entry->aen_data.ioc.ioc_type = ioc_type; +	bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq, +				  BFA_AEN_CAT_IOC, event);  }  /* @@ -2541,14 +2970,6 @@ bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)  	return BFA_STATUS_OK;  } -/* - * Clear saved firmware trace - */ -void -bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc) -{ -	ioc->dbg_fwsave_once = BFA_TRUE; -}  /*   * Retrieve saved firmware trace from a prior IOC failure. @@ -2579,7 +3000,7 @@ bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)  	bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,  		    bfa_ioc_portid(ioc)); -	req->ioc_class = ioc->ioc_mc; +	req->clscode = cpu_to_be16(ioc->clscode);  	bfa_ioc_mbox_queue(ioc, &cmd);  } @@ -2700,14 +3121,17 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)  /*   * Save firmware trace if configured.   */ -static void -bfa_ioc_debug_save(struct bfa_ioc_s *ioc) +void +bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)  {  	int		tlen; -	if (ioc->dbg_fwsave_len) { -		tlen = ioc->dbg_fwsave_len; -		bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); +	if (ioc->dbg_fwsave_once) { +		ioc->dbg_fwsave_once = BFA_FALSE; +		if (ioc->dbg_fwsave_len) { +			tlen = ioc->dbg_fwsave_len; +			bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); +		}  	}  } @@ -2717,89 +3141,63 @@ bfa_ioc_debug_save(struct bfa_ioc_s *ioc)  static void  bfa_ioc_recover(struct bfa_ioc_s *ioc)  { -	if (ioc->dbg_fwsave_once) { -		ioc->dbg_fwsave_once = BFA_FALSE; -		bfa_ioc_debug_save(ioc); -	} -  	bfa_ioc_stats(ioc, ioc_hbfails); +	ioc->stats.hb_count = ioc->hb_count;  	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);  } -static void -bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc) -{ -	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL) -		return; -} -  /* - *  hal_iocpf_pvt BFA IOC PF private functions + *  BFA IOC PF private functions   */ -  static void -bfa_iocpf_enable(struct bfa_ioc_s *ioc) +bfa_iocpf_timeout(void *ioc_arg)  { -	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE); -} +	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg; -static void -bfa_iocpf_disable(struct bfa_ioc_s *ioc) -{ -	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE); +	bfa_trc(ioc, 0); +	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);  }  static void -bfa_iocpf_fail(struct bfa_ioc_s *ioc) +bfa_iocpf_sem_timeout(void *ioc_arg)  { -	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); -} +	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg; -static void -bfa_iocpf_initfail(struct bfa_ioc_s *ioc) -{ -	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); +	bfa_ioc_hw_sem_get(ioc);  }  static void -bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc) +bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)  { -	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); -} +	u32 fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc); -static void -bfa_iocpf_stop(struct bfa_ioc_s *ioc) -{ -	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); -} +	bfa_trc(ioc, fwstate); -static void -bfa_iocpf_timeout(void *ioc_arg) -{ -	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg; +	if (fwstate == BFI_IOC_DISABLED) { +		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY); +		return; +	} -	bfa_trc(ioc, 0); -	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT); +	if (ioc->iocpf.poll_time >= (3 * BFA_IOC_TOV)) +		bfa_iocpf_timeout(ioc); +	else { +		ioc->iocpf.poll_time += BFA_IOC_POLL_TOV; +		bfa_iocpf_poll_timer_start(ioc); +	}  }  static void -bfa_iocpf_sem_timeout(void *ioc_arg) +bfa_iocpf_poll_timeout(void *ioc_arg)  { -	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg; +	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg; -	bfa_ioc_hw_sem_get(ioc); +	bfa_ioc_poll_fwinit(ioc);  }  /*   *  bfa timer function   */  void -bfa_timer_init(struct bfa_timer_mod_s *mod) -{ -	INIT_LIST_HEAD(&mod->timer_q); -} - -void  bfa_timer_beat(struct bfa_timer_mod_s *mod)  {  	struct list_head *qh = &mod->timer_q; @@ -2843,8 +3241,8 @@ bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,  		    void (*timercb) (void *), void *arg, unsigned int timeout)  { -	bfa_assert(timercb != NULL); -	bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer)); +	WARN_ON(timercb == NULL); +	WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer));  	timer->timeout = timeout;  	timer->timercb = timercb; @@ -2859,7 +3257,3809 @@ bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,  void  bfa_timer_stop(struct bfa_timer_s *timer)  { -	bfa_assert(!list_empty(&timer->qe)); +	WARN_ON(list_empty(&timer->qe));  	list_del(&timer->qe);  } + +/* + *	ASIC block related + */ +static void +bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg) +{ +	struct bfa_ablk_cfg_inst_s *cfg_inst; +	int i, j; +	u16	be16; + +	for (i = 0; i < BFA_ABLK_MAX; i++) { +		cfg_inst = &cfg->inst[i]; +		for (j = 0; j < BFA_ABLK_MAX_PFS; j++) { +			be16 = cfg_inst->pf_cfg[j].pers; +			cfg_inst->pf_cfg[j].pers = be16_to_cpu(be16); +			be16 = cfg_inst->pf_cfg[j].num_qpairs; +			cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16); +			be16 = cfg_inst->pf_cfg[j].num_vectors; +			cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16); +			be16 = cfg_inst->pf_cfg[j].bw_min; +			cfg_inst->pf_cfg[j].bw_min = be16_to_cpu(be16); +			be16 = cfg_inst->pf_cfg[j].bw_max; +			cfg_inst->pf_cfg[j].bw_max = be16_to_cpu(be16); +		} +	} +} + +static void +bfa_ablk_isr(void *cbarg, struct bfi_mbmsg_s *msg) +{ +	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg; +	struct bfi_ablk_i2h_rsp_s *rsp = (struct bfi_ablk_i2h_rsp_s *)msg; +	bfa_ablk_cbfn_t cbfn; + +	WARN_ON(msg->mh.msg_class != BFI_MC_ABLK); +	bfa_trc(ablk->ioc, msg->mh.msg_id); + +	switch (msg->mh.msg_id) { +	case BFI_ABLK_I2H_QUERY: +		if (rsp->status == BFA_STATUS_OK) { +			memcpy(ablk->cfg, ablk->dma_addr.kva, +				sizeof(struct bfa_ablk_cfg_s)); +			bfa_ablk_config_swap(ablk->cfg); +			ablk->cfg = NULL; +		} +		break; + +	case BFI_ABLK_I2H_ADPT_CONFIG: +	case BFI_ABLK_I2H_PORT_CONFIG: +		/* update config port mode */ +		ablk->ioc->port_mode_cfg = rsp->port_mode; + +	case BFI_ABLK_I2H_PF_DELETE: +	case BFI_ABLK_I2H_PF_UPDATE: +	case BFI_ABLK_I2H_OPTROM_ENABLE: +	case BFI_ABLK_I2H_OPTROM_DISABLE: +		/* No-op */ +		break; + +	case BFI_ABLK_I2H_PF_CREATE: +		*(ablk->pcifn) = rsp->pcifn; +		ablk->pcifn = NULL; +		break; + +	default: +		WARN_ON(1); +	} + +	ablk->busy = BFA_FALSE; +	if (ablk->cbfn) { +		cbfn = ablk->cbfn; +		ablk->cbfn = NULL; +		cbfn(ablk->cbarg, rsp->status); +	} +} + +static void +bfa_ablk_notify(void *cbarg, enum bfa_ioc_event_e event) +{ +	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg; + +	bfa_trc(ablk->ioc, event); + +	switch (event) { +	case BFA_IOC_E_ENABLED: +		WARN_ON(ablk->busy != BFA_FALSE); +		break; + +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		/* Fail any pending requests */ +		ablk->pcifn = NULL; +		if (ablk->busy) { +			if (ablk->cbfn) +				ablk->cbfn(ablk->cbarg, BFA_STATUS_FAILED); +			ablk->cbfn = NULL; +			ablk->busy = BFA_FALSE; +		} +		break; + +	default: +		WARN_ON(1); +		break; +	} +} + +u32 +bfa_ablk_meminfo(void) +{ +	return BFA_ROUNDUP(sizeof(struct bfa_ablk_cfg_s), BFA_DMA_ALIGN_SZ); +} + +void +bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa) +{ +	ablk->dma_addr.kva = dma_kva; +	ablk->dma_addr.pa  = dma_pa; +} + +void +bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc) +{ +	ablk->ioc = ioc; + +	bfa_ioc_mbox_regisr(ablk->ioc, BFI_MC_ABLK, bfa_ablk_isr, ablk); +	bfa_q_qe_init(&ablk->ioc_notify); +	bfa_ioc_notify_init(&ablk->ioc_notify, bfa_ablk_notify, ablk); +	list_add_tail(&ablk->ioc_notify.qe, &ablk->ioc->notify_q); +} + +bfa_status_t +bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg, +		bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_query_s *m; + +	WARN_ON(!ablk_cfg); + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->cfg = ablk_cfg; +	ablk->cbfn  = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_query_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_QUERY, +		    bfa_ioc_portid(ablk->ioc)); +	bfa_dma_be_addr_set(m->addr, ablk->dma_addr.pa); +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn, +		u8 port, enum bfi_pcifn_class personality, +		u16 bw_min, u16 bw_max, +		bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_pf_req_s *m; + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->pcifn = pcifn; +	ablk->cbfn = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE, +		    bfa_ioc_portid(ablk->ioc)); +	m->pers = cpu_to_be16((u16)personality); +	m->bw_min = cpu_to_be16(bw_min); +	m->bw_max = cpu_to_be16(bw_max); +	m->port = port; +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn, +		bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_pf_req_s *m; + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->cbfn  = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_DELETE, +		    bfa_ioc_portid(ablk->ioc)); +	m->pcifn = (u8)pcifn; +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_ablk_adapter_config(struct bfa_ablk_s *ablk, enum bfa_mode_s mode, +		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_cfg_req_s *m; + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->cbfn  = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_ADPT_CONFIG, +		    bfa_ioc_portid(ablk->ioc)); +	m->mode = (u8)mode; +	m->max_pf = (u8)max_pf; +	m->max_vf = (u8)max_vf; +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode, +		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_cfg_req_s *m; + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->cbfn  = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PORT_CONFIG, +		bfa_ioc_portid(ablk->ioc)); +	m->port = (u8)port; +	m->mode = (u8)mode; +	m->max_pf = (u8)max_pf; +	m->max_vf = (u8)max_vf; +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, u16 bw_min, +		   u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_pf_req_s *m; + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->cbfn  = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE, +		bfa_ioc_portid(ablk->ioc)); +	m->pcifn = (u8)pcifn; +	m->bw_min = cpu_to_be16(bw_min); +	m->bw_max = cpu_to_be16(bw_max); +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_ablk_optrom_en(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_optrom_s *m; + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->cbfn  = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_ENABLE, +		bfa_ioc_portid(ablk->ioc)); +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +bfa_status_t +bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_ablk_h2i_optrom_s *m; + +	if (!bfa_ioc_is_operational(ablk->ioc)) { +		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE); +		return BFA_STATUS_IOC_FAILURE; +	} + +	if (ablk->busy) { +		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY); +		return  BFA_STATUS_DEVBUSY; +	} + +	ablk->cbfn  = cbfn; +	ablk->cbarg = cbarg; +	ablk->busy  = BFA_TRUE; + +	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg; +	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_DISABLE, +		bfa_ioc_portid(ablk->ioc)); +	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); + +	return BFA_STATUS_OK; +} + +/* + *	SFP module specific + */ + +/* forward declarations */ +static void bfa_sfp_getdata_send(struct bfa_sfp_s *sfp); +static void bfa_sfp_media_get(struct bfa_sfp_s *sfp); +static bfa_status_t bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, +				enum bfa_port_speed portspeed); + +static void +bfa_cb_sfp_show(struct bfa_sfp_s *sfp) +{ +	bfa_trc(sfp, sfp->lock); +	if (sfp->cbfn) +		sfp->cbfn(sfp->cbarg, sfp->status); +	sfp->lock = 0; +	sfp->cbfn = NULL; +} + +static void +bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp) +{ +	bfa_trc(sfp, sfp->portspeed); +	if (sfp->media) { +		bfa_sfp_media_get(sfp); +		if (sfp->state_query_cbfn) +			sfp->state_query_cbfn(sfp->state_query_cbarg, +					sfp->status); +			sfp->media = NULL; +		} + +		if (sfp->portspeed) { +			sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed); +			if (sfp->state_query_cbfn) +				sfp->state_query_cbfn(sfp->state_query_cbarg, +						sfp->status); +				sfp->portspeed = BFA_PORT_SPEED_UNKNOWN; +		} + +		sfp->state_query_lock = 0; +		sfp->state_query_cbfn = NULL; +} + +/* + *	IOC event handler. + */ +static void +bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event) +{ +	struct bfa_sfp_s *sfp = sfp_arg; + +	bfa_trc(sfp, event); +	bfa_trc(sfp, sfp->lock); +	bfa_trc(sfp, sfp->state_query_lock); + +	switch (event) { +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		if (sfp->lock) { +			sfp->status = BFA_STATUS_IOC_FAILURE; +			bfa_cb_sfp_show(sfp); +		} + +		if (sfp->state_query_lock) { +			sfp->status = BFA_STATUS_IOC_FAILURE; +			bfa_cb_sfp_state_query(sfp); +		} +		break; + +	default: +		break; +	} +} + +/* + * SFP's State Change Notification post to AEN + */ +static void +bfa_sfp_scn_aen_post(struct bfa_sfp_s *sfp, struct bfi_sfp_scn_s *rsp) +{ +	struct bfad_s *bfad = (struct bfad_s *)sfp->ioc->bfa->bfad; +	struct bfa_aen_entry_s  *aen_entry; +	enum bfa_port_aen_event aen_evt = 0; + +	bfa_trc(sfp, (((u64)rsp->pomlvl) << 16) | (((u64)rsp->sfpid) << 8) | +		      ((u64)rsp->event)); + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	aen_entry->aen_data.port.ioc_type = bfa_ioc_get_type(sfp->ioc); +	aen_entry->aen_data.port.pwwn = sfp->ioc->attr->pwwn; +	aen_entry->aen_data.port.mac = bfa_ioc_get_mac(sfp->ioc); + +	switch (rsp->event) { +	case BFA_SFP_SCN_INSERTED: +		aen_evt = BFA_PORT_AEN_SFP_INSERT; +		break; +	case BFA_SFP_SCN_REMOVED: +		aen_evt = BFA_PORT_AEN_SFP_REMOVE; +		break; +	case BFA_SFP_SCN_FAILED: +		aen_evt = BFA_PORT_AEN_SFP_ACCESS_ERROR; +		break; +	case BFA_SFP_SCN_UNSUPPORT: +		aen_evt = BFA_PORT_AEN_SFP_UNSUPPORT; +		break; +	case BFA_SFP_SCN_POM: +		aen_evt = BFA_PORT_AEN_SFP_POM; +		aen_entry->aen_data.port.level = rsp->pomlvl; +		break; +	default: +		bfa_trc(sfp, rsp->event); +		WARN_ON(1); +	} + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++sfp->ioc->ioc_aen_seq, +				  BFA_AEN_CAT_PORT, aen_evt); +} + +/* + *	SFP get data send + */ +static void +bfa_sfp_getdata_send(struct bfa_sfp_s *sfp) +{ +	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg; + +	bfa_trc(sfp, req->memtype); + +	/* build host command */ +	bfi_h2i_set(req->mh, BFI_MC_SFP, BFI_SFP_H2I_SHOW, +			bfa_ioc_portid(sfp->ioc)); + +	/* send mbox cmd */ +	bfa_ioc_mbox_queue(sfp->ioc, &sfp->mbcmd); +} + +/* + *	SFP is valid, read sfp data + */ +static void +bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype) +{ +	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg; + +	WARN_ON(sfp->lock != 0); +	bfa_trc(sfp, sfp->state); + +	sfp->lock = 1; +	sfp->memtype = memtype; +	req->memtype = memtype; + +	/* Setup SG list */ +	bfa_alen_set(&req->alen, sizeof(struct sfp_mem_s), sfp->dbuf_pa); + +	bfa_sfp_getdata_send(sfp); +} + +/* + *	SFP scn handler + */ +static void +bfa_sfp_scn(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg) +{ +	struct bfi_sfp_scn_s *rsp = (struct bfi_sfp_scn_s *) msg; + +	switch (rsp->event) { +	case BFA_SFP_SCN_INSERTED: +		sfp->state = BFA_SFP_STATE_INSERTED; +		sfp->data_valid = 0; +		bfa_sfp_scn_aen_post(sfp, rsp); +		break; +	case BFA_SFP_SCN_REMOVED: +		sfp->state = BFA_SFP_STATE_REMOVED; +		sfp->data_valid = 0; +		bfa_sfp_scn_aen_post(sfp, rsp); +		 break; +	case BFA_SFP_SCN_FAILED: +		sfp->state = BFA_SFP_STATE_FAILED; +		sfp->data_valid = 0; +		bfa_sfp_scn_aen_post(sfp, rsp); +		break; +	case BFA_SFP_SCN_UNSUPPORT: +		sfp->state = BFA_SFP_STATE_UNSUPPORT; +		bfa_sfp_scn_aen_post(sfp, rsp); +		if (!sfp->lock) +			bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL); +		break; +	case BFA_SFP_SCN_POM: +		bfa_sfp_scn_aen_post(sfp, rsp); +		break; +	case BFA_SFP_SCN_VALID: +		sfp->state = BFA_SFP_STATE_VALID; +		if (!sfp->lock) +			bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL); +		break; +	default: +		bfa_trc(sfp, rsp->event); +		WARN_ON(1); +	} +} + +/* + * SFP show complete + */ +static void +bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg) +{ +	struct bfi_sfp_rsp_s *rsp = (struct bfi_sfp_rsp_s *) msg; + +	if (!sfp->lock) { +		/* +		 * receiving response after ioc failure +		 */ +		bfa_trc(sfp, sfp->lock); +		return; +	} + +	bfa_trc(sfp, rsp->status); +	if (rsp->status == BFA_STATUS_OK) { +		sfp->data_valid = 1; +		if (sfp->state == BFA_SFP_STATE_VALID) +			sfp->status = BFA_STATUS_OK; +		else if (sfp->state == BFA_SFP_STATE_UNSUPPORT) +			sfp->status = BFA_STATUS_SFP_UNSUPP; +		else +			bfa_trc(sfp, sfp->state); +	} else { +		sfp->data_valid = 0; +		sfp->status = rsp->status; +		/* sfpshow shouldn't change sfp state */ +	} + +	bfa_trc(sfp, sfp->memtype); +	if (sfp->memtype == BFI_SFP_MEM_DIAGEXT) { +		bfa_trc(sfp, sfp->data_valid); +		if (sfp->data_valid) { +			u32	size = sizeof(struct sfp_mem_s); +			u8 *des = (u8 *) &(sfp->sfpmem); +			memcpy(des, sfp->dbuf_kva, size); +		} +		/* +		 * Queue completion callback. +		 */ +		bfa_cb_sfp_show(sfp); +	} else +		sfp->lock = 0; + +	bfa_trc(sfp, sfp->state_query_lock); +	if (sfp->state_query_lock) { +		sfp->state = rsp->state; +		/* Complete callback */ +		bfa_cb_sfp_state_query(sfp); +	} +} + +/* + *	SFP query fw sfp state + */ +static void +bfa_sfp_state_query(struct bfa_sfp_s *sfp) +{ +	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg; + +	/* Should not be doing query if not in _INIT state */ +	WARN_ON(sfp->state != BFA_SFP_STATE_INIT); +	WARN_ON(sfp->state_query_lock != 0); +	bfa_trc(sfp, sfp->state); + +	sfp->state_query_lock = 1; +	req->memtype = 0; + +	if (!sfp->lock) +		bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL); +} + +static void +bfa_sfp_media_get(struct bfa_sfp_s *sfp) +{ +	enum bfa_defs_sfp_media_e *media = sfp->media; + +	*media = BFA_SFP_MEDIA_UNKNOWN; + +	if (sfp->state == BFA_SFP_STATE_UNSUPPORT) +		*media = BFA_SFP_MEDIA_UNSUPPORT; +	else if (sfp->state == BFA_SFP_STATE_VALID) { +		union sfp_xcvr_e10g_code_u e10g; +		struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva; +		u16 xmtr_tech = (sfpmem->srlid_base.xcvr[4] & 0x3) << 7 | +				(sfpmem->srlid_base.xcvr[5] >> 1); + +		e10g.b = sfpmem->srlid_base.xcvr[0]; +		bfa_trc(sfp, e10g.b); +		bfa_trc(sfp, xmtr_tech); +		/* check fc transmitter tech */ +		if ((xmtr_tech & SFP_XMTR_TECH_CU) || +		    (xmtr_tech & SFP_XMTR_TECH_CP) || +		    (xmtr_tech & SFP_XMTR_TECH_CA)) +			*media = BFA_SFP_MEDIA_CU; +		else if ((xmtr_tech & SFP_XMTR_TECH_EL_INTRA) || +			 (xmtr_tech & SFP_XMTR_TECH_EL_INTER)) +			*media = BFA_SFP_MEDIA_EL; +		else if ((xmtr_tech & SFP_XMTR_TECH_LL) || +			 (xmtr_tech & SFP_XMTR_TECH_LC)) +			*media = BFA_SFP_MEDIA_LW; +		else if ((xmtr_tech & SFP_XMTR_TECH_SL) || +			 (xmtr_tech & SFP_XMTR_TECH_SN) || +			 (xmtr_tech & SFP_XMTR_TECH_SA)) +			*media = BFA_SFP_MEDIA_SW; +		/* Check 10G Ethernet Compilance code */ +		else if (e10g.r.e10g_sr) +			*media = BFA_SFP_MEDIA_SW; +		else if (e10g.r.e10g_lrm && e10g.r.e10g_lr) +			*media = BFA_SFP_MEDIA_LW; +		else if (e10g.r.e10g_unall) +			*media = BFA_SFP_MEDIA_UNKNOWN; +		else +			bfa_trc(sfp, 0); +	} else +		bfa_trc(sfp, sfp->state); +} + +static bfa_status_t +bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed) +{ +	struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva; +	struct sfp_xcvr_s *xcvr = (struct sfp_xcvr_s *) sfpmem->srlid_base.xcvr; +	union sfp_xcvr_fc3_code_u fc3 = xcvr->fc3; +	union sfp_xcvr_e10g_code_u e10g = xcvr->e10g; + +	if (portspeed == BFA_PORT_SPEED_10GBPS) { +		if (e10g.r.e10g_sr || e10g.r.e10g_lr) +			return BFA_STATUS_OK; +		else { +			bfa_trc(sfp, e10g.b); +			return BFA_STATUS_UNSUPP_SPEED; +		} +	} +	if (((portspeed & BFA_PORT_SPEED_16GBPS) && fc3.r.mb1600) || +	    ((portspeed & BFA_PORT_SPEED_8GBPS) && fc3.r.mb800) || +	    ((portspeed & BFA_PORT_SPEED_4GBPS) && fc3.r.mb400) || +	    ((portspeed & BFA_PORT_SPEED_2GBPS) && fc3.r.mb200) || +	    ((portspeed & BFA_PORT_SPEED_1GBPS) && fc3.r.mb100)) +		return BFA_STATUS_OK; +	else { +		bfa_trc(sfp, portspeed); +		bfa_trc(sfp, fc3.b); +		bfa_trc(sfp, e10g.b); +		return BFA_STATUS_UNSUPP_SPEED; +	} +} + +/* + *	SFP hmbox handler + */ +void +bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg) +{ +	struct bfa_sfp_s *sfp = sfparg; + +	switch (msg->mh.msg_id) { +	case BFI_SFP_I2H_SHOW: +		bfa_sfp_show_comp(sfp, msg); +		break; + +	case BFI_SFP_I2H_SCN: +		bfa_sfp_scn(sfp, msg); +		break; + +	default: +		bfa_trc(sfp, msg->mh.msg_id); +		WARN_ON(1); +	} +} + +/* + *	Return DMA memory needed by sfp module. + */ +u32 +bfa_sfp_meminfo(void) +{ +	return BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ); +} + +/* + *	Attach virtual and physical memory for SFP. + */ +void +bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, void *dev, +		struct bfa_trc_mod_s *trcmod) +{ +	sfp->dev = dev; +	sfp->ioc = ioc; +	sfp->trcmod = trcmod; + +	sfp->cbfn = NULL; +	sfp->cbarg = NULL; +	sfp->sfpmem = NULL; +	sfp->lock = 0; +	sfp->data_valid = 0; +	sfp->state = BFA_SFP_STATE_INIT; +	sfp->state_query_lock = 0; +	sfp->state_query_cbfn = NULL; +	sfp->state_query_cbarg = NULL; +	sfp->media = NULL; +	sfp->portspeed = BFA_PORT_SPEED_UNKNOWN; +	sfp->is_elb = BFA_FALSE; + +	bfa_ioc_mbox_regisr(sfp->ioc, BFI_MC_SFP, bfa_sfp_intr, sfp); +	bfa_q_qe_init(&sfp->ioc_notify); +	bfa_ioc_notify_init(&sfp->ioc_notify, bfa_sfp_notify, sfp); +	list_add_tail(&sfp->ioc_notify.qe, &sfp->ioc->notify_q); +} + +/* + *	Claim Memory for SFP + */ +void +bfa_sfp_memclaim(struct bfa_sfp_s *sfp, u8 *dm_kva, u64 dm_pa) +{ +	sfp->dbuf_kva   = dm_kva; +	sfp->dbuf_pa    = dm_pa; +	memset(sfp->dbuf_kva, 0, sizeof(struct sfp_mem_s)); + +	dm_kva += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ); +	dm_pa += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ); +} + +/* + * Show SFP eeprom content + * + * @param[in] sfp   - bfa sfp module + * + * @param[out] sfpmem - sfp eeprom data + * + */ +bfa_status_t +bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem, +		bfa_cb_sfp_t cbfn, void *cbarg) +{ + +	if (!bfa_ioc_is_operational(sfp->ioc)) { +		bfa_trc(sfp, 0); +		return BFA_STATUS_IOC_NON_OP; +	} + +	if (sfp->lock) { +		bfa_trc(sfp, 0); +		return BFA_STATUS_DEVBUSY; +	} + +	sfp->cbfn = cbfn; +	sfp->cbarg = cbarg; +	sfp->sfpmem = sfpmem; + +	bfa_sfp_getdata(sfp, BFI_SFP_MEM_DIAGEXT); +	return BFA_STATUS_OK; +} + +/* + * Return SFP Media type + * + * @param[in] sfp   - bfa sfp module + * + * @param[out] media - port speed from user + * + */ +bfa_status_t +bfa_sfp_media(struct bfa_sfp_s *sfp, enum bfa_defs_sfp_media_e *media, +		bfa_cb_sfp_t cbfn, void *cbarg) +{ +	if (!bfa_ioc_is_operational(sfp->ioc)) { +		bfa_trc(sfp, 0); +		return BFA_STATUS_IOC_NON_OP; +	} + +	sfp->media = media; +	if (sfp->state == BFA_SFP_STATE_INIT) { +		if (sfp->state_query_lock) { +			bfa_trc(sfp, 0); +			return BFA_STATUS_DEVBUSY; +		} else { +			sfp->state_query_cbfn = cbfn; +			sfp->state_query_cbarg = cbarg; +			bfa_sfp_state_query(sfp); +			return BFA_STATUS_SFP_NOT_READY; +		} +	} + +	bfa_sfp_media_get(sfp); +	return BFA_STATUS_OK; +} + +/* + * Check if user set port speed is allowed by the SFP + * + * @param[in] sfp   - bfa sfp module + * @param[in] portspeed - port speed from user + * + */ +bfa_status_t +bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed, +		bfa_cb_sfp_t cbfn, void *cbarg) +{ +	WARN_ON(portspeed == BFA_PORT_SPEED_UNKNOWN); + +	if (!bfa_ioc_is_operational(sfp->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	/* For Mezz card, all speed is allowed */ +	if (bfa_mfg_is_mezz(sfp->ioc->attr->card_type)) +		return BFA_STATUS_OK; + +	/* Check SFP state */ +	sfp->portspeed = portspeed; +	if (sfp->state == BFA_SFP_STATE_INIT) { +		if (sfp->state_query_lock) { +			bfa_trc(sfp, 0); +			return BFA_STATUS_DEVBUSY; +		} else { +			sfp->state_query_cbfn = cbfn; +			sfp->state_query_cbarg = cbarg; +			bfa_sfp_state_query(sfp); +			return BFA_STATUS_SFP_NOT_READY; +		} +	} + +	if (sfp->state == BFA_SFP_STATE_REMOVED || +	    sfp->state == BFA_SFP_STATE_FAILED) { +		bfa_trc(sfp, sfp->state); +		return BFA_STATUS_NO_SFP_DEV; +	} + +	if (sfp->state == BFA_SFP_STATE_INSERTED) { +		bfa_trc(sfp, sfp->state); +		return BFA_STATUS_DEVBUSY;  /* sfp is reading data */ +	} + +	/* For eloopback, all speed is allowed */ +	if (sfp->is_elb) +		return BFA_STATUS_OK; + +	return bfa_sfp_speed_valid(sfp, portspeed); +} + +/* + *	Flash module specific + */ + +/* + * FLASH DMA buffer should be big enough to hold both MFG block and + * asic block(64k) at the same time and also should be 2k aligned to + * avoid write segement to cross sector boundary. + */ +#define BFA_FLASH_SEG_SZ	2048 +#define BFA_FLASH_DMA_BUF_SZ	\ +	BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ) + +static void +bfa_flash_aen_audit_post(struct bfa_ioc_s *ioc, enum bfa_audit_aen_event event, +			int inst, int type) +{ +	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; +	struct bfa_aen_entry_s  *aen_entry; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	aen_entry->aen_data.audit.pwwn = ioc->attr->pwwn; +	aen_entry->aen_data.audit.partition_inst = inst; +	aen_entry->aen_data.audit.partition_type = type; + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq, +				  BFA_AEN_CAT_AUDIT, event); +} + +static void +bfa_flash_cb(struct bfa_flash_s *flash) +{ +	flash->op_busy = 0; +	if (flash->cbfn) +		flash->cbfn(flash->cbarg, flash->status); +} + +static void +bfa_flash_notify(void *cbarg, enum bfa_ioc_event_e event) +{ +	struct bfa_flash_s	*flash = cbarg; + +	bfa_trc(flash, event); +	switch (event) { +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		if (flash->op_busy) { +			flash->status = BFA_STATUS_IOC_FAILURE; +			flash->cbfn(flash->cbarg, flash->status); +			flash->op_busy = 0; +		} +		break; + +	default: +		break; +	} +} + +/* + * Send flash attribute query request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_flash_query_send(void *cbarg) +{ +	struct bfa_flash_s *flash = cbarg; +	struct bfi_flash_query_req_s *msg = +			(struct bfi_flash_query_req_s *) flash->mb.msg; + +	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ, +		bfa_ioc_portid(flash->ioc)); +	bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr_s), +		flash->dbuf_pa); +	bfa_ioc_mbox_queue(flash->ioc, &flash->mb); +} + +/* + * Send flash write request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_flash_write_send(struct bfa_flash_s *flash) +{ +	struct bfi_flash_write_req_s *msg = +			(struct bfi_flash_write_req_s *) flash->mb.msg; +	u32	len; + +	msg->type = be32_to_cpu(flash->type); +	msg->instance = flash->instance; +	msg->offset = be32_to_cpu(flash->addr_off + flash->offset); +	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ? +		flash->residue : BFA_FLASH_DMA_BUF_SZ; +	msg->length = be32_to_cpu(len); + +	/* indicate if it's the last msg of the whole write operation */ +	msg->last = (len == flash->residue) ? 1 : 0; + +	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ, +			bfa_ioc_portid(flash->ioc)); +	bfa_alen_set(&msg->alen, len, flash->dbuf_pa); +	memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len); +	bfa_ioc_mbox_queue(flash->ioc, &flash->mb); + +	flash->residue -= len; +	flash->offset += len; +} + +/* + * Send flash read request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_flash_read_send(void *cbarg) +{ +	struct bfa_flash_s *flash = cbarg; +	struct bfi_flash_read_req_s *msg = +			(struct bfi_flash_read_req_s *) flash->mb.msg; +	u32	len; + +	msg->type = be32_to_cpu(flash->type); +	msg->instance = flash->instance; +	msg->offset = be32_to_cpu(flash->addr_off + flash->offset); +	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ? +			flash->residue : BFA_FLASH_DMA_BUF_SZ; +	msg->length = be32_to_cpu(len); +	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ, +		bfa_ioc_portid(flash->ioc)); +	bfa_alen_set(&msg->alen, len, flash->dbuf_pa); +	bfa_ioc_mbox_queue(flash->ioc, &flash->mb); +} + +/* + * Send flash erase request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_flash_erase_send(void *cbarg) +{ +	struct bfa_flash_s *flash = cbarg; +	struct bfi_flash_erase_req_s *msg = +			(struct bfi_flash_erase_req_s *) flash->mb.msg; + +	msg->type = be32_to_cpu(flash->type); +	msg->instance = flash->instance; +	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_ERASE_REQ, +			bfa_ioc_portid(flash->ioc)); +	bfa_ioc_mbox_queue(flash->ioc, &flash->mb); +} + +/* + * Process flash response messages upon receiving interrupts. + * + * @param[in] flasharg - flash structure + * @param[in] msg - message structure + */ +static void +bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg) +{ +	struct bfa_flash_s *flash = flasharg; +	u32	status; + +	union { +		struct bfi_flash_query_rsp_s *query; +		struct bfi_flash_erase_rsp_s *erase; +		struct bfi_flash_write_rsp_s *write; +		struct bfi_flash_read_rsp_s *read; +		struct bfi_flash_event_s *event; +		struct bfi_mbmsg_s   *msg; +	} m; + +	m.msg = msg; +	bfa_trc(flash, msg->mh.msg_id); + +	if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT) { +		/* receiving response after ioc failure */ +		bfa_trc(flash, 0x9999); +		return; +	} + +	switch (msg->mh.msg_id) { +	case BFI_FLASH_I2H_QUERY_RSP: +		status = be32_to_cpu(m.query->status); +		bfa_trc(flash, status); +		if (status == BFA_STATUS_OK) { +			u32	i; +			struct bfa_flash_attr_s *attr, *f; + +			attr = (struct bfa_flash_attr_s *) flash->ubuf; +			f = (struct bfa_flash_attr_s *) flash->dbuf_kva; +			attr->status = be32_to_cpu(f->status); +			attr->npart = be32_to_cpu(f->npart); +			bfa_trc(flash, attr->status); +			bfa_trc(flash, attr->npart); +			for (i = 0; i < attr->npart; i++) { +				attr->part[i].part_type = +					be32_to_cpu(f->part[i].part_type); +				attr->part[i].part_instance = +					be32_to_cpu(f->part[i].part_instance); +				attr->part[i].part_off = +					be32_to_cpu(f->part[i].part_off); +				attr->part[i].part_size = +					be32_to_cpu(f->part[i].part_size); +				attr->part[i].part_len = +					be32_to_cpu(f->part[i].part_len); +				attr->part[i].part_status = +					be32_to_cpu(f->part[i].part_status); +			} +		} +		flash->status = status; +		bfa_flash_cb(flash); +		break; +	case BFI_FLASH_I2H_ERASE_RSP: +		status = be32_to_cpu(m.erase->status); +		bfa_trc(flash, status); +		flash->status = status; +		bfa_flash_cb(flash); +		break; +	case BFI_FLASH_I2H_WRITE_RSP: +		status = be32_to_cpu(m.write->status); +		bfa_trc(flash, status); +		if (status != BFA_STATUS_OK || flash->residue == 0) { +			flash->status = status; +			bfa_flash_cb(flash); +		} else { +			bfa_trc(flash, flash->offset); +			bfa_flash_write_send(flash); +		} +		break; +	case BFI_FLASH_I2H_READ_RSP: +		status = be32_to_cpu(m.read->status); +		bfa_trc(flash, status); +		if (status != BFA_STATUS_OK) { +			flash->status = status; +			bfa_flash_cb(flash); +		} else { +			u32 len = be32_to_cpu(m.read->length); +			bfa_trc(flash, flash->offset); +			bfa_trc(flash, len); +			memcpy(flash->ubuf + flash->offset, +				flash->dbuf_kva, len); +			flash->residue -= len; +			flash->offset += len; +			if (flash->residue == 0) { +				flash->status = status; +				bfa_flash_cb(flash); +			} else +				bfa_flash_read_send(flash); +		} +		break; +	case BFI_FLASH_I2H_BOOT_VER_RSP: +		break; +	case BFI_FLASH_I2H_EVENT: +		status = be32_to_cpu(m.event->status); +		bfa_trc(flash, status); +		if (status == BFA_STATUS_BAD_FWCFG) +			bfa_ioc_aen_post(flash->ioc, BFA_IOC_AEN_FWCFG_ERROR); +		else if (status == BFA_STATUS_INVALID_VENDOR) { +			u32 param; +			param = be32_to_cpu(m.event->param); +			bfa_trc(flash, param); +			bfa_ioc_aen_post(flash->ioc, +				BFA_IOC_AEN_INVALID_VENDOR); +		} +		break; + +	default: +		WARN_ON(1); +	} +} + +/* + * Flash memory info API. + * + * @param[in] mincfg - minimal cfg variable + */ +u32 +bfa_flash_meminfo(bfa_boolean_t mincfg) +{ +	/* min driver doesn't need flash */ +	if (mincfg) +		return 0; +	return BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +} + +/* + * Flash attach API. + * + * @param[in] flash - flash structure + * @param[in] ioc  - ioc structure + * @param[in] dev  - device structure + * @param[in] trcmod - trace module + * @param[in] logmod - log module + */ +void +bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, void *dev, +		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg) +{ +	flash->ioc = ioc; +	flash->trcmod = trcmod; +	flash->cbfn = NULL; +	flash->cbarg = NULL; +	flash->op_busy = 0; + +	bfa_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash); +	bfa_q_qe_init(&flash->ioc_notify); +	bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash); +	list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q); + +	/* min driver doesn't need flash */ +	if (mincfg) { +		flash->dbuf_kva = NULL; +		flash->dbuf_pa = 0; +	} +} + +/* + * Claim memory for flash + * + * @param[in] flash - flash structure + * @param[in] dm_kva - pointer to virtual memory address + * @param[in] dm_pa - physical memory address + * @param[in] mincfg - minimal cfg variable + */ +void +bfa_flash_memclaim(struct bfa_flash_s *flash, u8 *dm_kva, u64 dm_pa, +		bfa_boolean_t mincfg) +{ +	if (mincfg) +		return; + +	flash->dbuf_kva = dm_kva; +	flash->dbuf_pa = dm_pa; +	memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ); +	dm_kva += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +	dm_pa += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +} + +/* + * Get flash attribute. + * + * @param[in] flash - flash structure + * @param[in] attr - flash attribute structure + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_flash_get_attr(struct bfa_flash_s *flash, struct bfa_flash_attr_s *attr, +		bfa_cb_flash_t cbfn, void *cbarg) +{ +	bfa_trc(flash, BFI_FLASH_H2I_QUERY_REQ); + +	if (!bfa_ioc_is_operational(flash->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (flash->op_busy) { +		bfa_trc(flash, flash->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	flash->op_busy = 1; +	flash->cbfn = cbfn; +	flash->cbarg = cbarg; +	flash->ubuf = (u8 *) attr; +	bfa_flash_query_send(flash); + +	return BFA_STATUS_OK; +} + +/* + * Erase flash partition. + * + * @param[in] flash - flash structure + * @param[in] type - flash partition type + * @param[in] instance - flash partition instance + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type, +		u8 instance, bfa_cb_flash_t cbfn, void *cbarg) +{ +	bfa_trc(flash, BFI_FLASH_H2I_ERASE_REQ); +	bfa_trc(flash, type); +	bfa_trc(flash, instance); + +	if (!bfa_ioc_is_operational(flash->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (flash->op_busy) { +		bfa_trc(flash, flash->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	flash->op_busy = 1; +	flash->cbfn = cbfn; +	flash->cbarg = cbarg; +	flash->type = type; +	flash->instance = instance; + +	bfa_flash_erase_send(flash); +	bfa_flash_aen_audit_post(flash->ioc, BFA_AUDIT_AEN_FLASH_ERASE, +				instance, type); +	return BFA_STATUS_OK; +} + +/* + * Update flash partition. + * + * @param[in] flash - flash structure + * @param[in] type - flash partition type + * @param[in] instance - flash partition instance + * @param[in] buf - update data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to the partition starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_flash_update_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type, +		u8 instance, void *buf, u32 len, u32 offset, +		bfa_cb_flash_t cbfn, void *cbarg) +{ +	bfa_trc(flash, BFI_FLASH_H2I_WRITE_REQ); +	bfa_trc(flash, type); +	bfa_trc(flash, instance); +	bfa_trc(flash, len); +	bfa_trc(flash, offset); + +	if (!bfa_ioc_is_operational(flash->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	/* +	 * 'len' must be in word (4-byte) boundary +	 * 'offset' must be in sector (16kb) boundary +	 */ +	if (!len || (len & 0x03) || (offset & 0x00003FFF)) +		return BFA_STATUS_FLASH_BAD_LEN; + +	if (type == BFA_FLASH_PART_MFG) +		return BFA_STATUS_EINVAL; + +	if (flash->op_busy) { +		bfa_trc(flash, flash->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	flash->op_busy = 1; +	flash->cbfn = cbfn; +	flash->cbarg = cbarg; +	flash->type = type; +	flash->instance = instance; +	flash->residue = len; +	flash->offset = 0; +	flash->addr_off = offset; +	flash->ubuf = buf; + +	bfa_flash_write_send(flash); +	return BFA_STATUS_OK; +} + +/* + * Read flash partition. + * + * @param[in] flash - flash structure + * @param[in] type - flash partition type + * @param[in] instance - flash partition instance + * @param[in] buf - read data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to the partition starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type, +		u8 instance, void *buf, u32 len, u32 offset, +		bfa_cb_flash_t cbfn, void *cbarg) +{ +	bfa_trc(flash, BFI_FLASH_H2I_READ_REQ); +	bfa_trc(flash, type); +	bfa_trc(flash, instance); +	bfa_trc(flash, len); +	bfa_trc(flash, offset); + +	if (!bfa_ioc_is_operational(flash->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	/* +	 * 'len' must be in word (4-byte) boundary +	 * 'offset' must be in sector (16kb) boundary +	 */ +	if (!len || (len & 0x03) || (offset & 0x00003FFF)) +		return BFA_STATUS_FLASH_BAD_LEN; + +	if (flash->op_busy) { +		bfa_trc(flash, flash->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	flash->op_busy = 1; +	flash->cbfn = cbfn; +	flash->cbarg = cbarg; +	flash->type = type; +	flash->instance = instance; +	flash->residue = len; +	flash->offset = 0; +	flash->addr_off = offset; +	flash->ubuf = buf; +	bfa_flash_read_send(flash); + +	return BFA_STATUS_OK; +} + +/* + *	DIAG module specific + */ + +#define BFA_DIAG_MEMTEST_TOV	50000	/* memtest timeout in msec */ +#define CT2_BFA_DIAG_MEMTEST_TOV	(9*30*1000)  /* 4.5 min */ + +/* IOC event handler */ +static void +bfa_diag_notify(void *diag_arg, enum bfa_ioc_event_e event) +{ +	struct bfa_diag_s *diag = diag_arg; + +	bfa_trc(diag, event); +	bfa_trc(diag, diag->block); +	bfa_trc(diag, diag->fwping.lock); +	bfa_trc(diag, diag->tsensor.lock); + +	switch (event) { +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		if (diag->fwping.lock) { +			diag->fwping.status = BFA_STATUS_IOC_FAILURE; +			diag->fwping.cbfn(diag->fwping.cbarg, +					diag->fwping.status); +			diag->fwping.lock = 0; +		} + +		if (diag->tsensor.lock) { +			diag->tsensor.status = BFA_STATUS_IOC_FAILURE; +			diag->tsensor.cbfn(diag->tsensor.cbarg, +					   diag->tsensor.status); +			diag->tsensor.lock = 0; +		} + +		if (diag->block) { +			if (diag->timer_active) { +				bfa_timer_stop(&diag->timer); +				diag->timer_active = 0; +			} + +			diag->status = BFA_STATUS_IOC_FAILURE; +			diag->cbfn(diag->cbarg, diag->status); +			diag->block = 0; +		} +		break; + +	default: +		break; +	} +} + +static void +bfa_diag_memtest_done(void *cbarg) +{ +	struct bfa_diag_s *diag = cbarg; +	struct bfa_ioc_s  *ioc = diag->ioc; +	struct bfa_diag_memtest_result *res = diag->result; +	u32	loff = BFI_BOOT_MEMTEST_RES_ADDR; +	u32	pgnum, pgoff, i; + +	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); +	pgoff = PSS_SMEM_PGOFF(loff); + +	writel(pgnum, ioc->ioc_regs.host_page_num_fn); + +	for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) / +			 sizeof(u32)); i++) { +		/* read test result from smem */ +		*((u32 *) res + i) = +			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff); +		loff += sizeof(u32); +	} + +	/* Reset IOC fwstates to BFI_IOC_UNINIT */ +	bfa_ioc_reset_fwstate(ioc); + +	res->status = swab32(res->status); +	bfa_trc(diag, res->status); + +	if (res->status == BFI_BOOT_MEMTEST_RES_SIG) +		diag->status = BFA_STATUS_OK; +	else { +		diag->status = BFA_STATUS_MEMTEST_FAILED; +		res->addr = swab32(res->addr); +		res->exp = swab32(res->exp); +		res->act = swab32(res->act); +		res->err_status = swab32(res->err_status); +		res->err_status1 = swab32(res->err_status1); +		res->err_addr = swab32(res->err_addr); +		bfa_trc(diag, res->addr); +		bfa_trc(diag, res->exp); +		bfa_trc(diag, res->act); +		bfa_trc(diag, res->err_status); +		bfa_trc(diag, res->err_status1); +		bfa_trc(diag, res->err_addr); +	} +	diag->timer_active = 0; +	diag->cbfn(diag->cbarg, diag->status); +	diag->block = 0; +} + +/* + * Firmware ping + */ + +/* + * Perform DMA test directly + */ +static void +diag_fwping_send(struct bfa_diag_s *diag) +{ +	struct bfi_diag_fwping_req_s *fwping_req; +	u32	i; + +	bfa_trc(diag, diag->fwping.dbuf_pa); + +	/* fill DMA area with pattern */ +	for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) +		*((u32 *)diag->fwping.dbuf_kva + i) = diag->fwping.data; + +	/* Fill mbox msg */ +	fwping_req = (struct bfi_diag_fwping_req_s *)diag->fwping.mbcmd.msg; + +	/* Setup SG list */ +	bfa_alen_set(&fwping_req->alen, BFI_DIAG_DMA_BUF_SZ, +			diag->fwping.dbuf_pa); +	/* Set up dma count */ +	fwping_req->count = cpu_to_be32(diag->fwping.count); +	/* Set up data pattern */ +	fwping_req->data = diag->fwping.data; + +	/* build host command */ +	bfi_h2i_set(fwping_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_FWPING, +		bfa_ioc_portid(diag->ioc)); + +	/* send mbox cmd */ +	bfa_ioc_mbox_queue(diag->ioc, &diag->fwping.mbcmd); +} + +static void +diag_fwping_comp(struct bfa_diag_s *diag, +		 struct bfi_diag_fwping_rsp_s *diag_rsp) +{ +	u32	rsp_data = diag_rsp->data; +	u8	rsp_dma_status = diag_rsp->dma_status; + +	bfa_trc(diag, rsp_data); +	bfa_trc(diag, rsp_dma_status); + +	if (rsp_dma_status == BFA_STATUS_OK) { +		u32	i, pat; +		pat = (diag->fwping.count & 0x1) ? ~(diag->fwping.data) : +			diag->fwping.data; +		/* Check mbox data */ +		if (diag->fwping.data != rsp_data) { +			bfa_trc(diag, rsp_data); +			diag->fwping.result->dmastatus = +					BFA_STATUS_DATACORRUPTED; +			diag->fwping.status = BFA_STATUS_DATACORRUPTED; +			diag->fwping.cbfn(diag->fwping.cbarg, +					diag->fwping.status); +			diag->fwping.lock = 0; +			return; +		} +		/* Check dma pattern */ +		for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) { +			if (*((u32 *)diag->fwping.dbuf_kva + i) != pat) { +				bfa_trc(diag, i); +				bfa_trc(diag, pat); +				bfa_trc(diag, +					*((u32 *)diag->fwping.dbuf_kva + i)); +				diag->fwping.result->dmastatus = +						BFA_STATUS_DATACORRUPTED; +				diag->fwping.status = BFA_STATUS_DATACORRUPTED; +				diag->fwping.cbfn(diag->fwping.cbarg, +						diag->fwping.status); +				diag->fwping.lock = 0; +				return; +			} +		} +		diag->fwping.result->dmastatus = BFA_STATUS_OK; +		diag->fwping.status = BFA_STATUS_OK; +		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status); +		diag->fwping.lock = 0; +	} else { +		diag->fwping.status = BFA_STATUS_HDMA_FAILED; +		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status); +		diag->fwping.lock = 0; +	} +} + +/* + * Temperature Sensor + */ + +static void +diag_tempsensor_send(struct bfa_diag_s *diag) +{ +	struct bfi_diag_ts_req_s *msg; + +	msg = (struct bfi_diag_ts_req_s *)diag->tsensor.mbcmd.msg; +	bfa_trc(diag, msg->temp); +	/* build host command */ +	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_TEMPSENSOR, +		bfa_ioc_portid(diag->ioc)); +	/* send mbox cmd */ +	bfa_ioc_mbox_queue(diag->ioc, &diag->tsensor.mbcmd); +} + +static void +diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp) +{ +	if (!diag->tsensor.lock) { +		/* receiving response after ioc failure */ +		bfa_trc(diag, diag->tsensor.lock); +		return; +	} + +	/* +	 * ASIC junction tempsensor is a reg read operation +	 * it will always return OK +	 */ +	diag->tsensor.temp->temp = be16_to_cpu(rsp->temp); +	diag->tsensor.temp->ts_junc = rsp->ts_junc; +	diag->tsensor.temp->ts_brd = rsp->ts_brd; + +	if (rsp->ts_brd) { +		/* tsensor.temp->status is brd_temp status */ +		diag->tsensor.temp->status = rsp->status; +		if (rsp->status == BFA_STATUS_OK) { +			diag->tsensor.temp->brd_temp = +				be16_to_cpu(rsp->brd_temp); +		} else +			diag->tsensor.temp->brd_temp = 0; +	} + +	bfa_trc(diag, rsp->status); +	bfa_trc(diag, rsp->ts_junc); +	bfa_trc(diag, rsp->temp); +	bfa_trc(diag, rsp->ts_brd); +	bfa_trc(diag, rsp->brd_temp); + +	/* tsensor status is always good bcos we always have junction temp */ +	diag->tsensor.status = BFA_STATUS_OK; +	diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status); +	diag->tsensor.lock = 0; +} + +/* + *	LED Test command + */ +static void +diag_ledtest_send(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest) +{ +	struct bfi_diag_ledtest_req_s  *msg; + +	msg = (struct bfi_diag_ledtest_req_s *)diag->ledtest.mbcmd.msg; +	/* build host command */ +	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LEDTEST, +			bfa_ioc_portid(diag->ioc)); + +	/* +	 * convert the freq from N blinks per 10 sec to +	 * crossbow ontime value. We do it here because division is need +	 */ +	if (ledtest->freq) +		ledtest->freq = 500 / ledtest->freq; + +	if (ledtest->freq == 0) +		ledtest->freq = 1; + +	bfa_trc(diag, ledtest->freq); +	/* mcpy(&ledtest_req->req, ledtest, sizeof(bfa_diag_ledtest_t)); */ +	msg->cmd = (u8) ledtest->cmd; +	msg->color = (u8) ledtest->color; +	msg->portid = bfa_ioc_portid(diag->ioc); +	msg->led = ledtest->led; +	msg->freq = cpu_to_be16(ledtest->freq); + +	/* send mbox cmd */ +	bfa_ioc_mbox_queue(diag->ioc, &diag->ledtest.mbcmd); +} + +static void +diag_ledtest_comp(struct bfa_diag_s *diag, struct bfi_diag_ledtest_rsp_s *msg) +{ +	bfa_trc(diag, diag->ledtest.lock); +	diag->ledtest.lock = BFA_FALSE; +	/* no bfa_cb_queue is needed because driver is not waiting */ +} + +/* + * Port beaconing + */ +static void +diag_portbeacon_send(struct bfa_diag_s *diag, bfa_boolean_t beacon, u32 sec) +{ +	struct bfi_diag_portbeacon_req_s *msg; + +	msg = (struct bfi_diag_portbeacon_req_s *)diag->beacon.mbcmd.msg; +	/* build host command */ +	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_PORTBEACON, +		bfa_ioc_portid(diag->ioc)); +	msg->beacon = beacon; +	msg->period = cpu_to_be32(sec); +	/* send mbox cmd */ +	bfa_ioc_mbox_queue(diag->ioc, &diag->beacon.mbcmd); +} + +static void +diag_portbeacon_comp(struct bfa_diag_s *diag) +{ +	bfa_trc(diag, diag->beacon.state); +	diag->beacon.state = BFA_FALSE; +	if (diag->cbfn_beacon) +		diag->cbfn_beacon(diag->dev, BFA_FALSE, diag->beacon.link_e2e); +} + +/* + *	Diag hmbox handler + */ +void +bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg) +{ +	struct bfa_diag_s *diag = diagarg; + +	switch (msg->mh.msg_id) { +	case BFI_DIAG_I2H_PORTBEACON: +		diag_portbeacon_comp(diag); +		break; +	case BFI_DIAG_I2H_FWPING: +		diag_fwping_comp(diag, (struct bfi_diag_fwping_rsp_s *) msg); +		break; +	case BFI_DIAG_I2H_TEMPSENSOR: +		diag_tempsensor_comp(diag, (bfi_diag_ts_rsp_t *) msg); +		break; +	case BFI_DIAG_I2H_LEDTEST: +		diag_ledtest_comp(diag, (struct bfi_diag_ledtest_rsp_s *) msg); +		break; +	default: +		bfa_trc(diag, msg->mh.msg_id); +		WARN_ON(1); +	} +} + +/* + * Gen RAM Test + * + *   @param[in] *diag           - diag data struct + *   @param[in] *memtest        - mem test params input from upper layer, + *   @param[in] pattern         - mem test pattern + *   @param[in] *result         - mem test result + *   @param[in] cbfn            - mem test callback functioin + *   @param[in] cbarg           - callback functioin arg + * + *   @param[out] + */ +bfa_status_t +bfa_diag_memtest(struct bfa_diag_s *diag, struct bfa_diag_memtest_s *memtest, +		u32 pattern, struct bfa_diag_memtest_result *result, +		bfa_cb_diag_t cbfn, void *cbarg) +{ +	u32	memtest_tov; + +	bfa_trc(diag, pattern); + +	if (!bfa_ioc_adapter_is_disabled(diag->ioc)) +		return BFA_STATUS_ADAPTER_ENABLED; + +	/* check to see if there is another destructive diag cmd running */ +	if (diag->block) { +		bfa_trc(diag, diag->block); +		return BFA_STATUS_DEVBUSY; +	} else +		diag->block = 1; + +	diag->result = result; +	diag->cbfn = cbfn; +	diag->cbarg = cbarg; + +	/* download memtest code and take LPU0 out of reset */ +	bfa_ioc_boot(diag->ioc, BFI_FWBOOT_TYPE_MEMTEST, BFI_FWBOOT_ENV_OS); + +	memtest_tov = (bfa_ioc_asic_gen(diag->ioc) == BFI_ASIC_GEN_CT2) ? +		       CT2_BFA_DIAG_MEMTEST_TOV : BFA_DIAG_MEMTEST_TOV; +	bfa_timer_begin(diag->ioc->timer_mod, &diag->timer, +			bfa_diag_memtest_done, diag, memtest_tov); +	diag->timer_active = 1; +	return BFA_STATUS_OK; +} + +/* + * DIAG firmware ping command + * + *   @param[in] *diag           - diag data struct + *   @param[in] cnt             - dma loop count for testing PCIE + *   @param[in] data            - data pattern to pass in fw + *   @param[in] *result         - pt to bfa_diag_fwping_result_t data struct + *   @param[in] cbfn            - callback function + *   @param[in] *cbarg          - callback functioin arg + * + *   @param[out] + */ +bfa_status_t +bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, u32 data, +		struct bfa_diag_results_fwping *result, bfa_cb_diag_t cbfn, +		void *cbarg) +{ +	bfa_trc(diag, cnt); +	bfa_trc(diag, data); + +	if (!bfa_ioc_is_operational(diag->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (bfa_asic_id_ct2(bfa_ioc_devid((diag->ioc))) && +	    ((diag->ioc)->clscode == BFI_PCIFN_CLASS_ETH)) +		return BFA_STATUS_CMD_NOTSUPP; + +	/* check to see if there is another destructive diag cmd running */ +	if (diag->block || diag->fwping.lock) { +		bfa_trc(diag, diag->block); +		bfa_trc(diag, diag->fwping.lock); +		return BFA_STATUS_DEVBUSY; +	} + +	/* Initialization */ +	diag->fwping.lock = 1; +	diag->fwping.cbfn = cbfn; +	diag->fwping.cbarg = cbarg; +	diag->fwping.result = result; +	diag->fwping.data = data; +	diag->fwping.count = cnt; + +	/* Init test results */ +	diag->fwping.result->data = 0; +	diag->fwping.result->status = BFA_STATUS_OK; + +	/* kick off the first ping */ +	diag_fwping_send(diag); +	return BFA_STATUS_OK; +} + +/* + * Read Temperature Sensor + * + *   @param[in] *diag           - diag data struct + *   @param[in] *result         - pt to bfa_diag_temp_t data struct + *   @param[in] cbfn            - callback function + *   @param[in] *cbarg          - callback functioin arg + * + *   @param[out] + */ +bfa_status_t +bfa_diag_tsensor_query(struct bfa_diag_s *diag, +		struct bfa_diag_results_tempsensor_s *result, +		bfa_cb_diag_t cbfn, void *cbarg) +{ +	/* check to see if there is a destructive diag cmd running */ +	if (diag->block || diag->tsensor.lock) { +		bfa_trc(diag, diag->block); +		bfa_trc(diag, diag->tsensor.lock); +		return BFA_STATUS_DEVBUSY; +	} + +	if (!bfa_ioc_is_operational(diag->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	/* Init diag mod params */ +	diag->tsensor.lock = 1; +	diag->tsensor.temp = result; +	diag->tsensor.cbfn = cbfn; +	diag->tsensor.cbarg = cbarg; +	diag->tsensor.status = BFA_STATUS_OK; + +	/* Send msg to fw */ +	diag_tempsensor_send(diag); + +	return BFA_STATUS_OK; +} + +/* + * LED Test command + * + *   @param[in] *diag           - diag data struct + *   @param[in] *ledtest        - pt to ledtest data structure + * + *   @param[out] + */ +bfa_status_t +bfa_diag_ledtest(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest) +{ +	bfa_trc(diag, ledtest->cmd); + +	if (!bfa_ioc_is_operational(diag->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (diag->beacon.state) +		return BFA_STATUS_BEACON_ON; + +	if (diag->ledtest.lock) +		return BFA_STATUS_LEDTEST_OP; + +	/* Send msg to fw */ +	diag->ledtest.lock = BFA_TRUE; +	diag_ledtest_send(diag, ledtest); + +	return BFA_STATUS_OK; +} + +/* + * Port beaconing command + * + *   @param[in] *diag           - diag data struct + *   @param[in] beacon          - port beaconing 1:ON   0:OFF + *   @param[in] link_e2e_beacon - link beaconing 1:ON   0:OFF + *   @param[in] sec             - beaconing duration in seconds + * + *   @param[out] + */ +bfa_status_t +bfa_diag_beacon_port(struct bfa_diag_s *diag, bfa_boolean_t beacon, +		bfa_boolean_t link_e2e_beacon, uint32_t sec) +{ +	bfa_trc(diag, beacon); +	bfa_trc(diag, link_e2e_beacon); +	bfa_trc(diag, sec); + +	if (!bfa_ioc_is_operational(diag->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (diag->ledtest.lock) +		return BFA_STATUS_LEDTEST_OP; + +	if (diag->beacon.state && beacon)       /* beacon alread on */ +		return BFA_STATUS_BEACON_ON; + +	diag->beacon.state	= beacon; +	diag->beacon.link_e2e	= link_e2e_beacon; +	if (diag->cbfn_beacon) +		diag->cbfn_beacon(diag->dev, beacon, link_e2e_beacon); + +	/* Send msg to fw */ +	diag_portbeacon_send(diag, beacon, sec); + +	return BFA_STATUS_OK; +} + +/* + * Return DMA memory needed by diag module. + */ +u32 +bfa_diag_meminfo(void) +{ +	return BFA_ROUNDUP(BFI_DIAG_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +} + +/* + *	Attach virtual and physical memory for Diag. + */ +void +bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev, +	bfa_cb_diag_beacon_t cbfn_beacon, struct bfa_trc_mod_s *trcmod) +{ +	diag->dev = dev; +	diag->ioc = ioc; +	diag->trcmod = trcmod; + +	diag->block = 0; +	diag->cbfn = NULL; +	diag->cbarg = NULL; +	diag->result = NULL; +	diag->cbfn_beacon = cbfn_beacon; + +	bfa_ioc_mbox_regisr(diag->ioc, BFI_MC_DIAG, bfa_diag_intr, diag); +	bfa_q_qe_init(&diag->ioc_notify); +	bfa_ioc_notify_init(&diag->ioc_notify, bfa_diag_notify, diag); +	list_add_tail(&diag->ioc_notify.qe, &diag->ioc->notify_q); +} + +void +bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa) +{ +	diag->fwping.dbuf_kva = dm_kva; +	diag->fwping.dbuf_pa = dm_pa; +	memset(diag->fwping.dbuf_kva, 0, BFI_DIAG_DMA_BUF_SZ); +} + +/* + *	PHY module specific + */ +#define BFA_PHY_DMA_BUF_SZ	0x02000         /* 8k dma buffer */ +#define BFA_PHY_LOCK_STATUS	0x018878        /* phy semaphore status reg */ + +static void +bfa_phy_ntoh32(u32 *obuf, u32 *ibuf, int sz) +{ +	int i, m = sz >> 2; + +	for (i = 0; i < m; i++) +		obuf[i] = be32_to_cpu(ibuf[i]); +} + +static bfa_boolean_t +bfa_phy_present(struct bfa_phy_s *phy) +{ +	return (phy->ioc->attr->card_type == BFA_MFG_TYPE_LIGHTNING); +} + +static void +bfa_phy_notify(void *cbarg, enum bfa_ioc_event_e event) +{ +	struct bfa_phy_s *phy = cbarg; + +	bfa_trc(phy, event); + +	switch (event) { +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		if (phy->op_busy) { +			phy->status = BFA_STATUS_IOC_FAILURE; +			phy->cbfn(phy->cbarg, phy->status); +			phy->op_busy = 0; +		} +		break; + +	default: +		break; +	} +} + +/* + * Send phy attribute query request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_phy_query_send(void *cbarg) +{ +	struct bfa_phy_s *phy = cbarg; +	struct bfi_phy_query_req_s *msg = +			(struct bfi_phy_query_req_s *) phy->mb.msg; + +	msg->instance = phy->instance; +	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_QUERY_REQ, +		bfa_ioc_portid(phy->ioc)); +	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_attr_s), phy->dbuf_pa); +	bfa_ioc_mbox_queue(phy->ioc, &phy->mb); +} + +/* + * Send phy write request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_phy_write_send(void *cbarg) +{ +	struct bfa_phy_s *phy = cbarg; +	struct bfi_phy_write_req_s *msg = +			(struct bfi_phy_write_req_s *) phy->mb.msg; +	u32	len; +	u16	*buf, *dbuf; +	int	i, sz; + +	msg->instance = phy->instance; +	msg->offset = cpu_to_be32(phy->addr_off + phy->offset); +	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ? +			phy->residue : BFA_PHY_DMA_BUF_SZ; +	msg->length = cpu_to_be32(len); + +	/* indicate if it's the last msg of the whole write operation */ +	msg->last = (len == phy->residue) ? 1 : 0; + +	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_WRITE_REQ, +		bfa_ioc_portid(phy->ioc)); +	bfa_alen_set(&msg->alen, len, phy->dbuf_pa); + +	buf = (u16 *) (phy->ubuf + phy->offset); +	dbuf = (u16 *)phy->dbuf_kva; +	sz = len >> 1; +	for (i = 0; i < sz; i++) +		buf[i] = cpu_to_be16(dbuf[i]); + +	bfa_ioc_mbox_queue(phy->ioc, &phy->mb); + +	phy->residue -= len; +	phy->offset += len; +} + +/* + * Send phy read request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_phy_read_send(void *cbarg) +{ +	struct bfa_phy_s *phy = cbarg; +	struct bfi_phy_read_req_s *msg = +			(struct bfi_phy_read_req_s *) phy->mb.msg; +	u32	len; + +	msg->instance = phy->instance; +	msg->offset = cpu_to_be32(phy->addr_off + phy->offset); +	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ? +			phy->residue : BFA_PHY_DMA_BUF_SZ; +	msg->length = cpu_to_be32(len); +	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_READ_REQ, +		bfa_ioc_portid(phy->ioc)); +	bfa_alen_set(&msg->alen, len, phy->dbuf_pa); +	bfa_ioc_mbox_queue(phy->ioc, &phy->mb); +} + +/* + * Send phy stats request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_phy_stats_send(void *cbarg) +{ +	struct bfa_phy_s *phy = cbarg; +	struct bfi_phy_stats_req_s *msg = +			(struct bfi_phy_stats_req_s *) phy->mb.msg; + +	msg->instance = phy->instance; +	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_STATS_REQ, +		bfa_ioc_portid(phy->ioc)); +	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_stats_s), phy->dbuf_pa); +	bfa_ioc_mbox_queue(phy->ioc, &phy->mb); +} + +/* + * Flash memory info API. + * + * @param[in] mincfg - minimal cfg variable + */ +u32 +bfa_phy_meminfo(bfa_boolean_t mincfg) +{ +	/* min driver doesn't need phy */ +	if (mincfg) +		return 0; + +	return BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +} + +/* + * Flash attach API. + * + * @param[in] phy - phy structure + * @param[in] ioc  - ioc structure + * @param[in] dev  - device structure + * @param[in] trcmod - trace module + * @param[in] logmod - log module + */ +void +bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc, void *dev, +		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg) +{ +	phy->ioc = ioc; +	phy->trcmod = trcmod; +	phy->cbfn = NULL; +	phy->cbarg = NULL; +	phy->op_busy = 0; + +	bfa_ioc_mbox_regisr(phy->ioc, BFI_MC_PHY, bfa_phy_intr, phy); +	bfa_q_qe_init(&phy->ioc_notify); +	bfa_ioc_notify_init(&phy->ioc_notify, bfa_phy_notify, phy); +	list_add_tail(&phy->ioc_notify.qe, &phy->ioc->notify_q); + +	/* min driver doesn't need phy */ +	if (mincfg) { +		phy->dbuf_kva = NULL; +		phy->dbuf_pa = 0; +	} +} + +/* + * Claim memory for phy + * + * @param[in] phy - phy structure + * @param[in] dm_kva - pointer to virtual memory address + * @param[in] dm_pa - physical memory address + * @param[in] mincfg - minimal cfg variable + */ +void +bfa_phy_memclaim(struct bfa_phy_s *phy, u8 *dm_kva, u64 dm_pa, +		bfa_boolean_t mincfg) +{ +	if (mincfg) +		return; + +	phy->dbuf_kva = dm_kva; +	phy->dbuf_pa = dm_pa; +	memset(phy->dbuf_kva, 0, BFA_PHY_DMA_BUF_SZ); +	dm_kva += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +	dm_pa += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +} + +bfa_boolean_t +bfa_phy_busy(struct bfa_ioc_s *ioc) +{ +	void __iomem	*rb; + +	rb = bfa_ioc_bar0(ioc); +	return readl(rb + BFA_PHY_LOCK_STATUS); +} + +/* + * Get phy attribute. + * + * @param[in] phy - phy structure + * @param[in] attr - phy attribute structure + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance, +		struct bfa_phy_attr_s *attr, bfa_cb_phy_t cbfn, void *cbarg) +{ +	bfa_trc(phy, BFI_PHY_H2I_QUERY_REQ); +	bfa_trc(phy, instance); + +	if (!bfa_phy_present(phy)) +		return BFA_STATUS_PHY_NOT_PRESENT; + +	if (!bfa_ioc_is_operational(phy->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (phy->op_busy || bfa_phy_busy(phy->ioc)) { +		bfa_trc(phy, phy->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	phy->op_busy = 1; +	phy->cbfn = cbfn; +	phy->cbarg = cbarg; +	phy->instance = instance; +	phy->ubuf = (uint8_t *) attr; +	bfa_phy_query_send(phy); + +	return BFA_STATUS_OK; +} + +/* + * Get phy stats. + * + * @param[in] phy - phy structure + * @param[in] instance - phy image instance + * @param[in] stats - pointer to phy stats + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance, +		struct bfa_phy_stats_s *stats, +		bfa_cb_phy_t cbfn, void *cbarg) +{ +	bfa_trc(phy, BFI_PHY_H2I_STATS_REQ); +	bfa_trc(phy, instance); + +	if (!bfa_phy_present(phy)) +		return BFA_STATUS_PHY_NOT_PRESENT; + +	if (!bfa_ioc_is_operational(phy->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (phy->op_busy || bfa_phy_busy(phy->ioc)) { +		bfa_trc(phy, phy->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	phy->op_busy = 1; +	phy->cbfn = cbfn; +	phy->cbarg = cbarg; +	phy->instance = instance; +	phy->ubuf = (u8 *) stats; +	bfa_phy_stats_send(phy); + +	return BFA_STATUS_OK; +} + +/* + * Update phy image. + * + * @param[in] phy - phy structure + * @param[in] instance - phy image instance + * @param[in] buf - update data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_phy_update(struct bfa_phy_s *phy, u8 instance, +		void *buf, u32 len, u32 offset, +		bfa_cb_phy_t cbfn, void *cbarg) +{ +	bfa_trc(phy, BFI_PHY_H2I_WRITE_REQ); +	bfa_trc(phy, instance); +	bfa_trc(phy, len); +	bfa_trc(phy, offset); + +	if (!bfa_phy_present(phy)) +		return BFA_STATUS_PHY_NOT_PRESENT; + +	if (!bfa_ioc_is_operational(phy->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	/* 'len' must be in word (4-byte) boundary */ +	if (!len || (len & 0x03)) +		return BFA_STATUS_FAILED; + +	if (phy->op_busy || bfa_phy_busy(phy->ioc)) { +		bfa_trc(phy, phy->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	phy->op_busy = 1; +	phy->cbfn = cbfn; +	phy->cbarg = cbarg; +	phy->instance = instance; +	phy->residue = len; +	phy->offset = 0; +	phy->addr_off = offset; +	phy->ubuf = buf; + +	bfa_phy_write_send(phy); +	return BFA_STATUS_OK; +} + +/* + * Read phy image. + * + * @param[in] phy - phy structure + * @param[in] instance - phy image instance + * @param[in] buf - read data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_phy_read(struct bfa_phy_s *phy, u8 instance, +		void *buf, u32 len, u32 offset, +		bfa_cb_phy_t cbfn, void *cbarg) +{ +	bfa_trc(phy, BFI_PHY_H2I_READ_REQ); +	bfa_trc(phy, instance); +	bfa_trc(phy, len); +	bfa_trc(phy, offset); + +	if (!bfa_phy_present(phy)) +		return BFA_STATUS_PHY_NOT_PRESENT; + +	if (!bfa_ioc_is_operational(phy->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	/* 'len' must be in word (4-byte) boundary */ +	if (!len || (len & 0x03)) +		return BFA_STATUS_FAILED; + +	if (phy->op_busy || bfa_phy_busy(phy->ioc)) { +		bfa_trc(phy, phy->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	phy->op_busy = 1; +	phy->cbfn = cbfn; +	phy->cbarg = cbarg; +	phy->instance = instance; +	phy->residue = len; +	phy->offset = 0; +	phy->addr_off = offset; +	phy->ubuf = buf; +	bfa_phy_read_send(phy); + +	return BFA_STATUS_OK; +} + +/* + * Process phy response messages upon receiving interrupts. + * + * @param[in] phyarg - phy structure + * @param[in] msg - message structure + */ +void +bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg) +{ +	struct bfa_phy_s *phy = phyarg; +	u32	status; + +	union { +		struct bfi_phy_query_rsp_s *query; +		struct bfi_phy_stats_rsp_s *stats; +		struct bfi_phy_write_rsp_s *write; +		struct bfi_phy_read_rsp_s *read; +		struct bfi_mbmsg_s   *msg; +	} m; + +	m.msg = msg; +	bfa_trc(phy, msg->mh.msg_id); + +	if (!phy->op_busy) { +		/* receiving response after ioc failure */ +		bfa_trc(phy, 0x9999); +		return; +	} + +	switch (msg->mh.msg_id) { +	case BFI_PHY_I2H_QUERY_RSP: +		status = be32_to_cpu(m.query->status); +		bfa_trc(phy, status); + +		if (status == BFA_STATUS_OK) { +			struct bfa_phy_attr_s *attr = +				(struct bfa_phy_attr_s *) phy->ubuf; +			bfa_phy_ntoh32((u32 *)attr, (u32 *)phy->dbuf_kva, +					sizeof(struct bfa_phy_attr_s)); +			bfa_trc(phy, attr->status); +			bfa_trc(phy, attr->length); +		} + +		phy->status = status; +		phy->op_busy = 0; +		if (phy->cbfn) +			phy->cbfn(phy->cbarg, phy->status); +		break; +	case BFI_PHY_I2H_STATS_RSP: +		status = be32_to_cpu(m.stats->status); +		bfa_trc(phy, status); + +		if (status == BFA_STATUS_OK) { +			struct bfa_phy_stats_s *stats = +				(struct bfa_phy_stats_s *) phy->ubuf; +			bfa_phy_ntoh32((u32 *)stats, (u32 *)phy->dbuf_kva, +				sizeof(struct bfa_phy_stats_s)); +				bfa_trc(phy, stats->status); +		} + +		phy->status = status; +		phy->op_busy = 0; +		if (phy->cbfn) +			phy->cbfn(phy->cbarg, phy->status); +		break; +	case BFI_PHY_I2H_WRITE_RSP: +		status = be32_to_cpu(m.write->status); +		bfa_trc(phy, status); + +		if (status != BFA_STATUS_OK || phy->residue == 0) { +			phy->status = status; +			phy->op_busy = 0; +			if (phy->cbfn) +				phy->cbfn(phy->cbarg, phy->status); +		} else { +			bfa_trc(phy, phy->offset); +			bfa_phy_write_send(phy); +		} +		break; +	case BFI_PHY_I2H_READ_RSP: +		status = be32_to_cpu(m.read->status); +		bfa_trc(phy, status); + +		if (status != BFA_STATUS_OK) { +			phy->status = status; +			phy->op_busy = 0; +			if (phy->cbfn) +				phy->cbfn(phy->cbarg, phy->status); +		} else { +			u32 len = be32_to_cpu(m.read->length); +			u16 *buf = (u16 *)(phy->ubuf + phy->offset); +			u16 *dbuf = (u16 *)phy->dbuf_kva; +			int i, sz = len >> 1; + +			bfa_trc(phy, phy->offset); +			bfa_trc(phy, len); + +			for (i = 0; i < sz; i++) +				buf[i] = be16_to_cpu(dbuf[i]); + +			phy->residue -= len; +			phy->offset += len; + +			if (phy->residue == 0) { +				phy->status = status; +				phy->op_busy = 0; +				if (phy->cbfn) +					phy->cbfn(phy->cbarg, phy->status); +			} else +				bfa_phy_read_send(phy); +		} +		break; +	default: +		WARN_ON(1); +	} +} + +/* + *	DCONF module specific + */ + +BFA_MODULE(dconf); + +/* + * DCONF state machine events + */ +enum bfa_dconf_event { +	BFA_DCONF_SM_INIT		= 1,	/* dconf Init */ +	BFA_DCONF_SM_FLASH_COMP		= 2,	/* read/write to flash */ +	BFA_DCONF_SM_WR			= 3,	/* binding change, map */ +	BFA_DCONF_SM_TIMEOUT		= 4,	/* Start timer */ +	BFA_DCONF_SM_EXIT		= 5,	/* exit dconf module */ +	BFA_DCONF_SM_IOCDISABLE		= 6,	/* IOC disable event */ +}; + +/* forward declaration of DCONF state machine */ +static void bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, +				enum bfa_dconf_event event); +static void bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf, +				enum bfa_dconf_event event); +static void bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf, +				enum bfa_dconf_event event); +static void bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf, +				enum bfa_dconf_event event); +static void bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf, +				enum bfa_dconf_event event); +static void bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf, +				enum bfa_dconf_event event); +static void bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf, +				enum bfa_dconf_event event); + +static void bfa_dconf_cbfn(void *dconf, bfa_status_t status); +static void bfa_dconf_timer(void *cbarg); +static bfa_status_t bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf); +static void bfa_dconf_init_cb(void *arg, bfa_status_t status); + +/* + * Beginning state of dconf module. Waiting for an event to start. + */ +static void +bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event) +{ +	bfa_status_t bfa_status; +	bfa_trc(dconf->bfa, event); + +	switch (event) { +	case BFA_DCONF_SM_INIT: +		if (dconf->min_cfg) { +			bfa_trc(dconf->bfa, dconf->min_cfg); +			bfa_fsm_send_event(&dconf->bfa->iocfc, +					IOCFC_E_DCONF_DONE); +			return; +		} +		bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read); +		bfa_timer_start(dconf->bfa, &dconf->timer, +			bfa_dconf_timer, dconf, 2 * BFA_DCONF_UPDATE_TOV); +		bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa), +					BFA_FLASH_PART_DRV, dconf->instance, +					dconf->dconf, +					sizeof(struct bfa_dconf_s), 0, +					bfa_dconf_init_cb, dconf->bfa); +		if (bfa_status != BFA_STATUS_OK) { +			bfa_timer_stop(&dconf->timer); +			bfa_dconf_init_cb(dconf->bfa, BFA_STATUS_FAILED); +			bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); +			return; +		} +		break; +	case BFA_DCONF_SM_EXIT: +		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE); +	case BFA_DCONF_SM_IOCDISABLE: +	case BFA_DCONF_SM_WR: +	case BFA_DCONF_SM_FLASH_COMP: +		break; +	default: +		bfa_sm_fault(dconf->bfa, event); +	} +} + +/* + * Read flash for dconf entries and make a call back to the driver once done. + */ +static void +bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf, +			enum bfa_dconf_event event) +{ +	bfa_trc(dconf->bfa, event); + +	switch (event) { +	case BFA_DCONF_SM_FLASH_COMP: +		bfa_timer_stop(&dconf->timer); +		bfa_sm_set_state(dconf, bfa_dconf_sm_ready); +		break; +	case BFA_DCONF_SM_TIMEOUT: +		bfa_sm_set_state(dconf, bfa_dconf_sm_ready); +		bfa_ioc_suspend(&dconf->bfa->ioc); +		break; +	case BFA_DCONF_SM_EXIT: +		bfa_timer_stop(&dconf->timer); +		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); +		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE); +		break; +	case BFA_DCONF_SM_IOCDISABLE: +		bfa_timer_stop(&dconf->timer); +		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); +		break; +	default: +		bfa_sm_fault(dconf->bfa, event); +	} +} + +/* + * DCONF Module is in ready state. Has completed the initialization. + */ +static void +bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event) +{ +	bfa_trc(dconf->bfa, event); + +	switch (event) { +	case BFA_DCONF_SM_WR: +		bfa_timer_start(dconf->bfa, &dconf->timer, +			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV); +		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty); +		break; +	case BFA_DCONF_SM_EXIT: +		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); +		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE); +		break; +	case BFA_DCONF_SM_INIT: +	case BFA_DCONF_SM_IOCDISABLE: +		break; +	default: +		bfa_sm_fault(dconf->bfa, event); +	} +} + +/* + * entries are dirty, write back to the flash. + */ + +static void +bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event) +{ +	bfa_trc(dconf->bfa, event); + +	switch (event) { +	case BFA_DCONF_SM_TIMEOUT: +		bfa_sm_set_state(dconf, bfa_dconf_sm_sync); +		bfa_dconf_flash_write(dconf); +		break; +	case BFA_DCONF_SM_WR: +		bfa_timer_stop(&dconf->timer); +		bfa_timer_start(dconf->bfa, &dconf->timer, +			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV); +		break; +	case BFA_DCONF_SM_EXIT: +		bfa_timer_stop(&dconf->timer); +		bfa_timer_start(dconf->bfa, &dconf->timer, +			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV); +		bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync); +		bfa_dconf_flash_write(dconf); +		break; +	case BFA_DCONF_SM_FLASH_COMP: +		break; +	case BFA_DCONF_SM_IOCDISABLE: +		bfa_timer_stop(&dconf->timer); +		bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty); +		break; +	default: +		bfa_sm_fault(dconf->bfa, event); +	} +} + +/* + * Sync the dconf entries to the flash. + */ +static void +bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf, +			enum bfa_dconf_event event) +{ +	bfa_trc(dconf->bfa, event); + +	switch (event) { +	case BFA_DCONF_SM_IOCDISABLE: +	case BFA_DCONF_SM_FLASH_COMP: +		bfa_timer_stop(&dconf->timer); +	case BFA_DCONF_SM_TIMEOUT: +		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); +		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE); +		break; +	default: +		bfa_sm_fault(dconf->bfa, event); +	} +} + +static void +bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event) +{ +	bfa_trc(dconf->bfa, event); + +	switch (event) { +	case BFA_DCONF_SM_FLASH_COMP: +		bfa_sm_set_state(dconf, bfa_dconf_sm_ready); +		break; +	case BFA_DCONF_SM_WR: +		bfa_timer_start(dconf->bfa, &dconf->timer, +			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV); +		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty); +		break; +	case BFA_DCONF_SM_EXIT: +		bfa_timer_start(dconf->bfa, &dconf->timer, +			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV); +		bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync); +		break; +	case BFA_DCONF_SM_IOCDISABLE: +		bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty); +		break; +	default: +		bfa_sm_fault(dconf->bfa, event); +	} +} + +static void +bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf, +			enum bfa_dconf_event event) +{ +	bfa_trc(dconf->bfa, event); + +	switch (event) { +	case BFA_DCONF_SM_INIT: +		bfa_timer_start(dconf->bfa, &dconf->timer, +			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV); +		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty); +		break; +	case BFA_DCONF_SM_EXIT: +		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); +		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE); +		break; +	case BFA_DCONF_SM_IOCDISABLE: +		break; +	default: +		bfa_sm_fault(dconf->bfa, event); +	} +} + +/* + * Compute and return memory needed by DRV_CFG module. + */ +static void +bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, +		  struct bfa_s *bfa) +{ +	struct bfa_mem_kva_s *dconf_kva = BFA_MEM_DCONF_KVA(bfa); + +	if (cfg->drvcfg.min_cfg) +		bfa_mem_kva_setup(meminfo, dconf_kva, +				sizeof(struct bfa_dconf_hdr_s)); +	else +		bfa_mem_kva_setup(meminfo, dconf_kva, +				sizeof(struct bfa_dconf_s)); +} + +static void +bfa_dconf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, +		struct bfa_pcidev_s *pcidev) +{ +	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); + +	dconf->bfad = bfad; +	dconf->bfa = bfa; +	dconf->instance = bfa->ioc.port_id; +	bfa_trc(bfa, dconf->instance); + +	dconf->dconf = (struct bfa_dconf_s *) bfa_mem_kva_curp(dconf); +	if (cfg->drvcfg.min_cfg) { +		bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_hdr_s); +		dconf->min_cfg = BFA_TRUE; +	} else { +		dconf->min_cfg = BFA_FALSE; +		bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_s); +	} + +	bfa_dconf_read_data_valid(bfa) = BFA_FALSE; +	bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); +} + +static void +bfa_dconf_init_cb(void *arg, bfa_status_t status) +{ +	struct bfa_s *bfa = arg; +	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); + +	if (status == BFA_STATUS_OK) { +		bfa_dconf_read_data_valid(bfa) = BFA_TRUE; +		if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE) +			dconf->dconf->hdr.signature = BFI_DCONF_SIGNATURE; +		if (dconf->dconf->hdr.version != BFI_DCONF_VERSION) +			dconf->dconf->hdr.version = BFI_DCONF_VERSION; +	} +	bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP); +	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE); +} + +void +bfa_dconf_modinit(struct bfa_s *bfa) +{ +	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); +	bfa_sm_send_event(dconf, BFA_DCONF_SM_INIT); +} +static void +bfa_dconf_start(struct bfa_s *bfa) +{ +} + +static void +bfa_dconf_stop(struct bfa_s *bfa) +{ +} + +static void bfa_dconf_timer(void *cbarg) +{ +	struct bfa_dconf_mod_s *dconf = cbarg; +	bfa_sm_send_event(dconf, BFA_DCONF_SM_TIMEOUT); +} +static void +bfa_dconf_iocdisable(struct bfa_s *bfa) +{ +	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); +	bfa_sm_send_event(dconf, BFA_DCONF_SM_IOCDISABLE); +} + +static void +bfa_dconf_detach(struct bfa_s *bfa) +{ +} + +static bfa_status_t +bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf) +{ +	bfa_status_t bfa_status; +	bfa_trc(dconf->bfa, 0); + +	bfa_status = bfa_flash_update_part(BFA_FLASH(dconf->bfa), +				BFA_FLASH_PART_DRV, dconf->instance, +				dconf->dconf,  sizeof(struct bfa_dconf_s), 0, +				bfa_dconf_cbfn, dconf); +	if (bfa_status != BFA_STATUS_OK) +		WARN_ON(bfa_status); +	bfa_trc(dconf->bfa, bfa_status); + +	return bfa_status; +} + +bfa_status_t +bfa_dconf_update(struct bfa_s *bfa) +{ +	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); +	bfa_trc(dconf->bfa, 0); +	if (bfa_sm_cmp_state(dconf, bfa_dconf_sm_iocdown_dirty)) +		return BFA_STATUS_FAILED; + +	if (dconf->min_cfg) { +		bfa_trc(dconf->bfa, dconf->min_cfg); +		return BFA_STATUS_FAILED; +	} + +	bfa_sm_send_event(dconf, BFA_DCONF_SM_WR); +	return BFA_STATUS_OK; +} + +static void +bfa_dconf_cbfn(void *arg, bfa_status_t status) +{ +	struct bfa_dconf_mod_s *dconf = arg; +	WARN_ON(status); +	bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP); +} + +void +bfa_dconf_modexit(struct bfa_s *bfa) +{ +	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); +	bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT); +} + +/* + * FRU specific functions + */ + +#define BFA_FRU_DMA_BUF_SZ	0x02000		/* 8k dma buffer */ +#define BFA_FRU_CHINOOK_MAX_SIZE 0x10000 +#define BFA_FRU_LIGHTNING_MAX_SIZE 0x200 + +static void +bfa_fru_notify(void *cbarg, enum bfa_ioc_event_e event) +{ +	struct bfa_fru_s *fru = cbarg; + +	bfa_trc(fru, event); + +	switch (event) { +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		if (fru->op_busy) { +			fru->status = BFA_STATUS_IOC_FAILURE; +			fru->cbfn(fru->cbarg, fru->status); +			fru->op_busy = 0; +		} +		break; + +	default: +		break; +	} +} + +/* + * Send fru write request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type) +{ +	struct bfa_fru_s *fru = cbarg; +	struct bfi_fru_write_req_s *msg = +			(struct bfi_fru_write_req_s *) fru->mb.msg; +	u32 len; + +	msg->offset = cpu_to_be32(fru->addr_off + fru->offset); +	len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ? +				fru->residue : BFA_FRU_DMA_BUF_SZ; +	msg->length = cpu_to_be32(len); + +	/* +	 * indicate if it's the last msg of the whole write operation +	 */ +	msg->last = (len == fru->residue) ? 1 : 0; + +	msg->trfr_cmpl = (len == fru->residue) ? fru->trfr_cmpl : 0; +	bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc)); +	bfa_alen_set(&msg->alen, len, fru->dbuf_pa); + +	memcpy(fru->dbuf_kva, fru->ubuf + fru->offset, len); +	bfa_ioc_mbox_queue(fru->ioc, &fru->mb); + +	fru->residue -= len; +	fru->offset += len; +} + +/* + * Send fru read request. + * + * @param[in] cbarg - callback argument + */ +static void +bfa_fru_read_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type) +{ +	struct bfa_fru_s *fru = cbarg; +	struct bfi_fru_read_req_s *msg = +			(struct bfi_fru_read_req_s *) fru->mb.msg; +	u32 len; + +	msg->offset = cpu_to_be32(fru->addr_off + fru->offset); +	len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ? +				fru->residue : BFA_FRU_DMA_BUF_SZ; +	msg->length = cpu_to_be32(len); +	bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc)); +	bfa_alen_set(&msg->alen, len, fru->dbuf_pa); +	bfa_ioc_mbox_queue(fru->ioc, &fru->mb); +} + +/* + * Flash memory info API. + * + * @param[in] mincfg - minimal cfg variable + */ +u32 +bfa_fru_meminfo(bfa_boolean_t mincfg) +{ +	/* min driver doesn't need fru */ +	if (mincfg) +		return 0; + +	return BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +} + +/* + * Flash attach API. + * + * @param[in] fru - fru structure + * @param[in] ioc  - ioc structure + * @param[in] dev  - device structure + * @param[in] trcmod - trace module + * @param[in] logmod - log module + */ +void +bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, void *dev, +	struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg) +{ +	fru->ioc = ioc; +	fru->trcmod = trcmod; +	fru->cbfn = NULL; +	fru->cbarg = NULL; +	fru->op_busy = 0; + +	bfa_ioc_mbox_regisr(fru->ioc, BFI_MC_FRU, bfa_fru_intr, fru); +	bfa_q_qe_init(&fru->ioc_notify); +	bfa_ioc_notify_init(&fru->ioc_notify, bfa_fru_notify, fru); +	list_add_tail(&fru->ioc_notify.qe, &fru->ioc->notify_q); + +	/* min driver doesn't need fru */ +	if (mincfg) { +		fru->dbuf_kva = NULL; +		fru->dbuf_pa = 0; +	} +} + +/* + * Claim memory for fru + * + * @param[in] fru - fru structure + * @param[in] dm_kva - pointer to virtual memory address + * @param[in] dm_pa - frusical memory address + * @param[in] mincfg - minimal cfg variable + */ +void +bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa, +	bfa_boolean_t mincfg) +{ +	if (mincfg) +		return; + +	fru->dbuf_kva = dm_kva; +	fru->dbuf_pa = dm_pa; +	memset(fru->dbuf_kva, 0, BFA_FRU_DMA_BUF_SZ); +	dm_kva += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +	dm_pa += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ); +} + +/* + * Update fru vpd image. + * + * @param[in] fru - fru structure + * @param[in] buf - update data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset, +		  bfa_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl) +{ +	bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ); +	bfa_trc(fru, len); +	bfa_trc(fru, offset); + +	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2 && +		fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2) +		return BFA_STATUS_FRU_NOT_PRESENT; + +	if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK) +		return BFA_STATUS_CMD_NOTSUPP; + +	if (!bfa_ioc_is_operational(fru->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (fru->op_busy) { +		bfa_trc(fru, fru->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	fru->op_busy = 1; + +	fru->cbfn = cbfn; +	fru->cbarg = cbarg; +	fru->residue = len; +	fru->offset = 0; +	fru->addr_off = offset; +	fru->ubuf = buf; +	fru->trfr_cmpl = trfr_cmpl; + +	bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ); + +	return BFA_STATUS_OK; +} + +/* + * Read fru vpd image. + * + * @param[in] fru - fru structure + * @param[in] buf - read data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset, +		bfa_cb_fru_t cbfn, void *cbarg) +{ +	bfa_trc(fru, BFI_FRUVPD_H2I_READ_REQ); +	bfa_trc(fru, len); +	bfa_trc(fru, offset); + +	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2) +		return BFA_STATUS_FRU_NOT_PRESENT; + +	if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK && +		fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2) +		return BFA_STATUS_CMD_NOTSUPP; + +	if (!bfa_ioc_is_operational(fru->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (fru->op_busy) { +		bfa_trc(fru, fru->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	fru->op_busy = 1; + +	fru->cbfn = cbfn; +	fru->cbarg = cbarg; +	fru->residue = len; +	fru->offset = 0; +	fru->addr_off = offset; +	fru->ubuf = buf; +	bfa_fru_read_send(fru, BFI_FRUVPD_H2I_READ_REQ); + +	return BFA_STATUS_OK; +} + +/* + * Get maximum size fru vpd image. + * + * @param[in] fru - fru structure + * @param[out] size - maximum size of fru vpd data + * + * Return status. + */ +bfa_status_t +bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size) +{ +	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2) +		return BFA_STATUS_FRU_NOT_PRESENT; + +	if (!bfa_ioc_is_operational(fru->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK || +		fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK2) +		*max_size = BFA_FRU_CHINOOK_MAX_SIZE; +	else +		return BFA_STATUS_CMD_NOTSUPP; +	return BFA_STATUS_OK; +} +/* + * tfru write. + * + * @param[in] fru - fru structure + * @param[in] buf - update data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_tfru_write(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset, +	       bfa_cb_fru_t cbfn, void *cbarg) +{ +	bfa_trc(fru, BFI_TFRU_H2I_WRITE_REQ); +	bfa_trc(fru, len); +	bfa_trc(fru, offset); +	bfa_trc(fru, *((u8 *) buf)); + +	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2) +		return BFA_STATUS_FRU_NOT_PRESENT; + +	if (!bfa_ioc_is_operational(fru->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (fru->op_busy) { +		bfa_trc(fru, fru->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	fru->op_busy = 1; + +	fru->cbfn = cbfn; +	fru->cbarg = cbarg; +	fru->residue = len; +	fru->offset = 0; +	fru->addr_off = offset; +	fru->ubuf = buf; + +	bfa_fru_write_send(fru, BFI_TFRU_H2I_WRITE_REQ); + +	return BFA_STATUS_OK; +} + +/* + * tfru read. + * + * @param[in] fru - fru structure + * @param[in] buf - read data buffer + * @param[in] len - data buffer length + * @param[in] offset - offset relative to starting address + * @param[in] cbfn - callback function + * @param[in] cbarg - callback argument + * + * Return status. + */ +bfa_status_t +bfa_tfru_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset, +	      bfa_cb_fru_t cbfn, void *cbarg) +{ +	bfa_trc(fru, BFI_TFRU_H2I_READ_REQ); +	bfa_trc(fru, len); +	bfa_trc(fru, offset); + +	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2) +		return BFA_STATUS_FRU_NOT_PRESENT; + +	if (!bfa_ioc_is_operational(fru->ioc)) +		return BFA_STATUS_IOC_NON_OP; + +	if (fru->op_busy) { +		bfa_trc(fru, fru->op_busy); +		return BFA_STATUS_DEVBUSY; +	} + +	fru->op_busy = 1; + +	fru->cbfn = cbfn; +	fru->cbarg = cbarg; +	fru->residue = len; +	fru->offset = 0; +	fru->addr_off = offset; +	fru->ubuf = buf; +	bfa_fru_read_send(fru, BFI_TFRU_H2I_READ_REQ); + +	return BFA_STATUS_OK; +} + +/* + * Process fru response messages upon receiving interrupts. + * + * @param[in] fruarg - fru structure + * @param[in] msg - message structure + */ +void +bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg) +{ +	struct bfa_fru_s *fru = fruarg; +	struct bfi_fru_rsp_s *rsp = (struct bfi_fru_rsp_s *)msg; +	u32 status; + +	bfa_trc(fru, msg->mh.msg_id); + +	if (!fru->op_busy) { +		/* +		 * receiving response after ioc failure +		 */ +		bfa_trc(fru, 0x9999); +		return; +	} + +	switch (msg->mh.msg_id) { +	case BFI_FRUVPD_I2H_WRITE_RSP: +	case BFI_TFRU_I2H_WRITE_RSP: +		status = be32_to_cpu(rsp->status); +		bfa_trc(fru, status); + +		if (status != BFA_STATUS_OK || fru->residue == 0) { +			fru->status = status; +			fru->op_busy = 0; +			if (fru->cbfn) +				fru->cbfn(fru->cbarg, fru->status); +		} else { +			bfa_trc(fru, fru->offset); +			if (msg->mh.msg_id == BFI_FRUVPD_I2H_WRITE_RSP) +				bfa_fru_write_send(fru, +					BFI_FRUVPD_H2I_WRITE_REQ); +			else +				bfa_fru_write_send(fru, +					BFI_TFRU_H2I_WRITE_REQ); +		} +		break; +	case BFI_FRUVPD_I2H_READ_RSP: +	case BFI_TFRU_I2H_READ_RSP: +		status = be32_to_cpu(rsp->status); +		bfa_trc(fru, status); + +		if (status != BFA_STATUS_OK) { +			fru->status = status; +			fru->op_busy = 0; +			if (fru->cbfn) +				fru->cbfn(fru->cbarg, fru->status); +		} else { +			u32 len = be32_to_cpu(rsp->length); + +			bfa_trc(fru, fru->offset); +			bfa_trc(fru, len); + +			memcpy(fru->ubuf + fru->offset, fru->dbuf_kva, len); +			fru->residue -= len; +			fru->offset += len; + +			if (fru->residue == 0) { +				fru->status = status; +				fru->op_busy = 0; +				if (fru->cbfn) +					fru->cbfn(fru->cbarg, fru->status); +			} else { +				if (msg->mh.msg_id == BFI_FRUVPD_I2H_READ_RSP) +					bfa_fru_read_send(fru, +						BFI_FRUVPD_H2I_READ_REQ); +				else +					bfa_fru_read_send(fru, +						BFI_TFRU_H2I_READ_REQ); +			} +		} +		break; +	default: +		WARN_ON(1); +	} +} + +/* + * register definitions + */ +#define FLI_CMD_REG			0x0001d000 +#define FLI_RDDATA_REG			0x0001d010 +#define FLI_ADDR_REG			0x0001d004 +#define FLI_DEV_STATUS_REG		0x0001d014 + +#define BFA_FLASH_FIFO_SIZE		128	/* fifo size */ +#define BFA_FLASH_CHECK_MAX		10000	/* max # of status check */ +#define BFA_FLASH_BLOCKING_OP_MAX	1000000	/* max # of blocking op check */ +#define BFA_FLASH_WIP_MASK		0x01	/* write in progress bit mask */ + +enum bfa_flash_cmd { +	BFA_FLASH_FAST_READ	= 0x0b,	/* fast read */ +	BFA_FLASH_READ_STATUS	= 0x05,	/* read status */ +}; + +/** + * @brief hardware error definition + */ +enum bfa_flash_err { +	BFA_FLASH_NOT_PRESENT	= -1,	/*!< flash not present */ +	BFA_FLASH_UNINIT	= -2,	/*!< flash not initialized */ +	BFA_FLASH_BAD		= -3,	/*!< flash bad */ +	BFA_FLASH_BUSY		= -4,	/*!< flash busy */ +	BFA_FLASH_ERR_CMD_ACT	= -5,	/*!< command active never cleared */ +	BFA_FLASH_ERR_FIFO_CNT	= -6,	/*!< fifo count never cleared */ +	BFA_FLASH_ERR_WIP	= -7,	/*!< write-in-progress never cleared */ +	BFA_FLASH_ERR_TIMEOUT	= -8,	/*!< fli timeout */ +	BFA_FLASH_ERR_LEN	= -9,	/*!< invalid length */ +}; + +/** + * @brief flash command register data structure + */ +union bfa_flash_cmd_reg_u { +	struct { +#ifdef __BIG_ENDIAN +		u32	act:1; +		u32	rsv:1; +		u32	write_cnt:9; +		u32	read_cnt:9; +		u32	addr_cnt:4; +		u32	cmd:8; +#else +		u32	cmd:8; +		u32	addr_cnt:4; +		u32	read_cnt:9; +		u32	write_cnt:9; +		u32	rsv:1; +		u32	act:1; +#endif +	} r; +	u32	i; +}; + +/** + * @brief flash device status register data structure + */ +union bfa_flash_dev_status_reg_u { +	struct { +#ifdef __BIG_ENDIAN +		u32	rsv:21; +		u32	fifo_cnt:6; +		u32	busy:1; +		u32	init_status:1; +		u32	present:1; +		u32	bad:1; +		u32	good:1; +#else +		u32	good:1; +		u32	bad:1; +		u32	present:1; +		u32	init_status:1; +		u32	busy:1; +		u32	fifo_cnt:6; +		u32	rsv:21; +#endif +	} r; +	u32	i; +}; + +/** + * @brief flash address register data structure + */ +union bfa_flash_addr_reg_u { +	struct { +#ifdef __BIG_ENDIAN +		u32	addr:24; +		u32	dummy:8; +#else +		u32	dummy:8; +		u32	addr:24; +#endif +	} r; +	u32	i; +}; + +/** + * dg flash_raw_private Flash raw private functions + */ +static void +bfa_flash_set_cmd(void __iomem *pci_bar, u8 wr_cnt, +		  u8 rd_cnt, u8 ad_cnt, u8 op) +{ +	union bfa_flash_cmd_reg_u cmd; + +	cmd.i = 0; +	cmd.r.act = 1; +	cmd.r.write_cnt = wr_cnt; +	cmd.r.read_cnt = rd_cnt; +	cmd.r.addr_cnt = ad_cnt; +	cmd.r.cmd = op; +	writel(cmd.i, (pci_bar + FLI_CMD_REG)); +} + +static void +bfa_flash_set_addr(void __iomem *pci_bar, u32 address) +{ +	union bfa_flash_addr_reg_u addr; + +	addr.r.addr = address & 0x00ffffff; +	addr.r.dummy = 0; +	writel(addr.i, (pci_bar + FLI_ADDR_REG)); +} + +static int +bfa_flash_cmd_act_check(void __iomem *pci_bar) +{ +	union bfa_flash_cmd_reg_u cmd; + +	cmd.i = readl(pci_bar + FLI_CMD_REG); + +	if (cmd.r.act) +		return BFA_FLASH_ERR_CMD_ACT; + +	return 0; +} + +/** + * @brief + * Flush FLI data fifo. + * + * @param[in] pci_bar - pci bar address + * @param[in] dev_status - device status + * + * Return 0 on success, negative error number on error. + */ +static u32 +bfa_flash_fifo_flush(void __iomem *pci_bar) +{ +	u32 i; +	u32 t; +	union bfa_flash_dev_status_reg_u dev_status; + +	dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG); + +	if (!dev_status.r.fifo_cnt) +		return 0; + +	/* fifo counter in terms of words */ +	for (i = 0; i < dev_status.r.fifo_cnt; i++) +		t = readl(pci_bar + FLI_RDDATA_REG); + +	/* +	 * Check the device status. It may take some time. +	 */ +	for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) { +		dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG); +		if (!dev_status.r.fifo_cnt) +			break; +	} + +	if (dev_status.r.fifo_cnt) +		return BFA_FLASH_ERR_FIFO_CNT; + +	return 0; +} + +/** + * @brief + * Read flash status. + * + * @param[in] pci_bar - pci bar address + * + * Return 0 on success, negative error number on error. +*/ +static u32 +bfa_flash_status_read(void __iomem *pci_bar) +{ +	union bfa_flash_dev_status_reg_u	dev_status; +	int				status; +	u32			ret_status; +	int				i; + +	status = bfa_flash_fifo_flush(pci_bar); +	if (status < 0) +		return status; + +	bfa_flash_set_cmd(pci_bar, 0, 4, 0, BFA_FLASH_READ_STATUS); + +	for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) { +		status = bfa_flash_cmd_act_check(pci_bar); +		if (!status) +			break; +	} + +	if (status) +		return status; + +	dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG); +	if (!dev_status.r.fifo_cnt) +		return BFA_FLASH_BUSY; + +	ret_status = readl(pci_bar + FLI_RDDATA_REG); +	ret_status >>= 24; + +	status = bfa_flash_fifo_flush(pci_bar); +	if (status < 0) +		return status; + +	return ret_status; +} + +/** + * @brief + * Start flash read operation. + * + * @param[in] pci_bar - pci bar address + * @param[in] offset - flash address offset + * @param[in] len - read data length + * @param[in] buf - read data buffer + * + * Return 0 on success, negative error number on error. + */ +static u32 +bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len, +			 char *buf) +{ +	int status; + +	/* +	 * len must be mutiple of 4 and not exceeding fifo size +	 */ +	if (len == 0 || len > BFA_FLASH_FIFO_SIZE || (len & 0x03) != 0) +		return BFA_FLASH_ERR_LEN; + +	/* +	 * check status +	 */ +	status = bfa_flash_status_read(pci_bar); +	if (status == BFA_FLASH_BUSY) +		status = bfa_flash_status_read(pci_bar); + +	if (status < 0) +		return status; + +	/* +	 * check if write-in-progress bit is cleared +	 */ +	if (status & BFA_FLASH_WIP_MASK) +		return BFA_FLASH_ERR_WIP; + +	bfa_flash_set_addr(pci_bar, offset); + +	bfa_flash_set_cmd(pci_bar, 0, (u8)len, 4, BFA_FLASH_FAST_READ); + +	return 0; +} + +/** + * @brief + * Check flash read operation. + * + * @param[in] pci_bar - pci bar address + * + * Return flash device status, 1 if busy, 0 if not. + */ +static u32 +bfa_flash_read_check(void __iomem *pci_bar) +{ +	if (bfa_flash_cmd_act_check(pci_bar)) +		return 1; + +	return 0; +} +/** + * @brief + * End flash read operation. + * + * @param[in] pci_bar - pci bar address + * @param[in] len - read data length + * @param[in] buf - read data buffer + * + */ +static void +bfa_flash_read_end(void __iomem *pci_bar, u32 len, char *buf) +{ + +	u32 i; + +	/* +	 * read data fifo up to 32 words +	 */ +	for (i = 0; i < len; i += 4) { +		u32 w = readl(pci_bar + FLI_RDDATA_REG); +		*((u32 *) (buf + i)) = swab32(w); +	} + +	bfa_flash_fifo_flush(pci_bar); +} + +/** + * @brief + * Perform flash raw read. + * + * @param[in] pci_bar - pci bar address + * @param[in] offset - flash partition address offset + * @param[in] buf - read data buffer + * @param[in] len - read data length + * + * Return status. + */ + + +#define FLASH_BLOCKING_OP_MAX   500 +#define FLASH_SEM_LOCK_REG	0x18820 + +static int +bfa_raw_sem_get(void __iomem *bar) +{ +	int	locked; + +	locked = readl((bar + FLASH_SEM_LOCK_REG)); +	return !locked; + +} + +bfa_status_t +bfa_flash_sem_get(void __iomem *bar) +{ +	u32 n = FLASH_BLOCKING_OP_MAX; + +	while (!bfa_raw_sem_get(bar)) { +		if (--n <= 0) +			return BFA_STATUS_BADFLASH; +		mdelay(10); +	} +	return BFA_STATUS_OK; +} + +void +bfa_flash_sem_put(void __iomem *bar) +{ +	writel(0, (bar + FLASH_SEM_LOCK_REG)); +} + +bfa_status_t +bfa_flash_raw_read(void __iomem *pci_bar, u32 offset, char *buf, +		       u32 len) +{ +	u32 n; +	int status; +	u32 off, l, s, residue, fifo_sz; + +	residue = len; +	off = 0; +	fifo_sz = BFA_FLASH_FIFO_SIZE; +	status = bfa_flash_sem_get(pci_bar); +	if (status != BFA_STATUS_OK) +		return status; + +	while (residue) { +		s = offset + off; +		n = s / fifo_sz; +		l = (n + 1) * fifo_sz - s; +		if (l > residue) +			l = residue; + +		status = bfa_flash_read_start(pci_bar, offset + off, l, +								&buf[off]); +		if (status < 0) { +			bfa_flash_sem_put(pci_bar); +			return BFA_STATUS_FAILED; +		} + +		n = BFA_FLASH_BLOCKING_OP_MAX; +		while (bfa_flash_read_check(pci_bar)) { +			if (--n <= 0) { +				bfa_flash_sem_put(pci_bar); +				return BFA_STATUS_FAILED; +			} +		} + +		bfa_flash_read_end(pci_bar, l, &buf[off]); + +		residue -= l; +		off += l; +	} +	bfa_flash_sem_put(pci_bar); + +	return BFA_STATUS_OK; +} diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 9c407a87a1a..2e28392c2fb 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -18,10 +18,15 @@  #ifndef __BFA_IOC_H__  #define __BFA_IOC_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h"  #include "bfa_cs.h"  #include "bfi.h" +#define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS) +#define BFA_DBG_FWTRC_LEN					\ +	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\ +	(sizeof(struct bfa_trc_mod_s) -				\ +	BFA_TRC_MAX * sizeof(struct bfa_trc_s)))  /*   * BFA timer declarations   */ @@ -47,7 +52,6 @@ struct bfa_timer_mod_s {  #define BFA_TIMER_FREQ 200 /* specified in millisecs */  void bfa_timer_beat(struct bfa_timer_mod_s *mod); -void bfa_timer_init(struct bfa_timer_mod_s *mod);  void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,  			bfa_timer_cbfn_t timercb, void *arg,  			unsigned int timeout); @@ -70,7 +74,7 @@ struct bfa_sge_s {  #define bfa_swap_words(_x)  (	\  	((_x) << 32) | ((_x) >> 32)) -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  #define bfa_sge_to_be(_x)  #define bfa_sge_to_le(_x)	bfa_sge_word_swap(_x)  #define bfa_sgaddr_le(_x)	bfa_swap_words(_x) @@ -81,12 +85,75 @@ struct bfa_sge_s {  #endif  /* + * BFA memory resources + */ +struct bfa_mem_dma_s { +	struct list_head qe;		/* Queue of DMA elements */ +	u32		mem_len;	/* Total Length in Bytes */ +	u8		*kva;		/* kernel virtual address */ +	u64		dma;		/* dma address if DMA memory */ +	u8		*kva_curp;	/* kva allocation cursor */ +	u64		dma_curp;	/* dma allocation cursor */ +}; +#define bfa_mem_dma_t struct bfa_mem_dma_s + +struct bfa_mem_kva_s { +	struct list_head qe;		/* Queue of KVA elements */ +	u32		mem_len;	/* Total Length in Bytes */ +	u8		*kva;		/* kernel virtual address */ +	u8		*kva_curp;	/* kva allocation cursor */ +}; +#define bfa_mem_kva_t struct bfa_mem_kva_s + +struct bfa_meminfo_s { +	struct bfa_mem_dma_s dma_info; +	struct bfa_mem_kva_s kva_info; +}; + +/* BFA memory segment setup macros */ +#define bfa_mem_dma_setup(_meminfo, _dm_ptr, _seg_sz) do {	\ +	((bfa_mem_dma_t *)(_dm_ptr))->mem_len = (_seg_sz);	\ +	if (_seg_sz)						\ +		list_add_tail(&((bfa_mem_dma_t *)_dm_ptr)->qe,	\ +			      &(_meminfo)->dma_info.qe);	\ +} while (0) + +#define bfa_mem_kva_setup(_meminfo, _kva_ptr, _seg_sz) do {	\ +	((bfa_mem_kva_t *)(_kva_ptr))->mem_len = (_seg_sz);	\ +	if (_seg_sz)						\ +		list_add_tail(&((bfa_mem_kva_t *)_kva_ptr)->qe,	\ +			      &(_meminfo)->kva_info.qe);	\ +} while (0) + +/* BFA dma memory segments iterator */ +#define bfa_mem_dma_sptr(_mod, _i)	(&(_mod)->dma_seg[(_i)]) +#define bfa_mem_dma_seg_iter(_mod, _sptr, _nr, _i)			\ +	for (_i = 0, _sptr = bfa_mem_dma_sptr(_mod, _i); _i < (_nr);	\ +	     _i++, _sptr = bfa_mem_dma_sptr(_mod, _i)) + +#define bfa_mem_kva_curp(_mod)	((_mod)->kva_seg.kva_curp) +#define bfa_mem_dma_virt(_sptr)	((_sptr)->kva_curp) +#define bfa_mem_dma_phys(_sptr)	((_sptr)->dma_curp) +#define bfa_mem_dma_len(_sptr)	((_sptr)->mem_len) + +/* Get the corresponding dma buf kva for a req - from the tag */ +#define bfa_mem_get_dmabuf_kva(_mod, _tag, _rqsz)			      \ +	(((u8 *)(_mod)->dma_seg[BFI_MEM_SEG_FROM_TAG(_tag, _rqsz)].kva_curp) +\ +	 BFI_MEM_SEG_REQ_OFFSET(_tag, _rqsz) * (_rqsz)) + +/* Get the corresponding dma buf pa for a req - from the tag */ +#define bfa_mem_get_dmabuf_pa(_mod, _tag, _rqsz)			\ +	((_mod)->dma_seg[BFI_MEM_SEG_FROM_TAG(_tag, _rqsz)].dma_curp +	\ +	 BFI_MEM_SEG_REQ_OFFSET(_tag, _rqsz) * (_rqsz)) + +/*   * PCI device information required by IOC   */  struct bfa_pcidev_s {  	int		pci_slot;  	u8		pci_func;  	u16		device_id; +	u16		ssid;  	void __iomem	*pci_bar_kva;  }; @@ -108,25 +175,23 @@ struct bfa_dma_s {  #define BFI_SMEM_CB_SIZE	0x200000U	/* ! 2MB for crossbow	*/  #define BFI_SMEM_CT_SIZE	0x280000U	/* ! 2.5MB for catapult	*/ - -#define bfa_dma_addr_set(dma_addr, pa)	\ -		__bfa_dma_addr_set(&dma_addr, (u64)pa) - +#define bfa_dma_be_addr_set(dma_addr, pa)	\ +		__bfa_dma_be_addr_set(&dma_addr, (u64)pa)  static inline void -__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa) +__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)  { -	dma_addr->a32.addr_lo = (u32) pa; -	dma_addr->a32.addr_hi = (u32) (bfa_os_u32(pa)); +	dma_addr->a32.addr_lo = cpu_to_be32(pa); +	dma_addr->a32.addr_hi = cpu_to_be32(pa >> 32);  } +#define bfa_alen_set(__alen, __len, __pa)	\ +	__bfa_alen_set(__alen, __len, (u64)__pa) -#define bfa_dma_be_addr_set(dma_addr, pa)	\ -		__bfa_dma_be_addr_set(&dma_addr, (u64)pa)  static inline void -__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa) +__bfa_alen_set(struct bfi_alen_s *alen, u32 len, u64 pa)  { -	dma_addr->a32.addr_lo = (u32) cpu_to_be32(pa); -	dma_addr->a32.addr_hi = (u32) cpu_to_be32(bfa_os_u32(pa)); +	alen->al_len = cpu_to_be32(len); +	bfa_dma_be_addr_set(alen->al_addr, pa);  }  struct bfa_ioc_regs_s { @@ -134,6 +199,7 @@ struct bfa_ioc_regs_s {  	void __iomem *hfn_mbox;  	void __iomem *lpu_mbox_cmd;  	void __iomem *lpu_mbox; +	void __iomem *lpu_read_stat;  	void __iomem *pss_ctl_reg;  	void __iomem *pss_err_status_reg;  	void __iomem *app_pll_fast_ctl_reg; @@ -145,8 +211,11 @@ struct bfa_ioc_regs_s {  	void __iomem *host_page_num_fn;  	void __iomem *heartbeat;  	void __iomem *ioc_fwstate; +	void __iomem *alt_ioc_fwstate;  	void __iomem *ll_halt; +	void __iomem *alt_ll_halt;  	void __iomem *err_set; +	void __iomem *ioc_fail_sync;  	void __iomem *shirq_isr_next;  	void __iomem *shirq_msk_next;  	void __iomem *smem_page_start; @@ -192,18 +261,26 @@ struct bfa_ioc_cbfn_s {  };  /* - * Heartbeat failure notification queue element. + * IOC event notification mechanism.   */ -struct bfa_ioc_hbfail_notify_s { +enum bfa_ioc_event_e { +	BFA_IOC_E_ENABLED	= 1, +	BFA_IOC_E_DISABLED	= 2, +	BFA_IOC_E_FAILED	= 3, +}; + +typedef void (*bfa_ioc_notify_cbfn_t)(void *, enum bfa_ioc_event_e); + +struct bfa_ioc_notify_s {  	struct list_head		qe; -	bfa_ioc_hbfail_cbfn_t	cbfn; +	bfa_ioc_notify_cbfn_t	cbfn;  	void			*cbarg;  };  /* - * Initialize a heartbeat failure notification structure + * Initialize a IOC event notification structure   */ -#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do {	\ +#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do {	\  	(__notify)->cbfn = (__cbfn);      \  	(__notify)->cbarg = (__cbarg);      \  } while (0) @@ -211,8 +288,9 @@ struct bfa_ioc_hbfail_notify_s {  struct bfa_iocpf_s {  	bfa_fsm_t		fsm;  	struct bfa_ioc_s	*ioc; -	u32		retry_count; +	bfa_boolean_t		fw_mismatch_notified;  	bfa_boolean_t		auto_recover; +	u32			poll_time;  };  struct bfa_ioc_s { @@ -224,17 +302,15 @@ struct bfa_ioc_s {  	struct bfa_timer_s	sem_timer;  	struct bfa_timer_s	hb_timer;  	u32		hb_count; -	struct list_head		hb_notify_q; +	struct list_head	notify_q;  	void			*dbg_fwsave;  	int			dbg_fwsave_len;  	bfa_boolean_t		dbg_fwsave_once; -	enum bfi_mclass		ioc_mc; +	enum bfi_pcifn_class	clscode;  	struct bfa_ioc_regs_s	ioc_regs;  	struct bfa_trc_mod_s	*trcmod;  	struct bfa_ioc_drv_stats_s	stats;  	bfa_boolean_t		fcmode; -	bfa_boolean_t		ctdev; -	bfa_boolean_t		cna;  	bfa_boolean_t		pllinit;  	bfa_boolean_t		stats_busy;	/*  outstanding stats */  	u8			port_id; @@ -244,24 +320,501 @@ struct bfa_ioc_s {  	struct bfa_ioc_mbox_mod_s mbox_mod;  	struct bfa_ioc_hwif_s	*ioc_hwif;  	struct bfa_iocpf_s	iocpf; +	enum bfi_asic_gen	asic_gen; +	enum bfi_asic_mode	asic_mode; +	enum bfi_port_mode	port0_mode; +	enum bfi_port_mode	port1_mode; +	enum bfa_mode_s		port_mode; +	u8			ad_cap_bm;	/* adapter cap bit mask */ +	u8			port_mode_cfg;	/* config port mode */ +	int			ioc_aen_seq;  };  struct bfa_ioc_hwif_s { -	bfa_status_t (*ioc_pll_init) (void __iomem *rb, bfa_boolean_t fcmode); +	bfa_status_t (*ioc_pll_init) (void __iomem *rb, enum bfi_asic_mode m);  	bfa_boolean_t	(*ioc_firmware_lock)	(struct bfa_ioc_s *ioc);  	void		(*ioc_firmware_unlock)	(struct bfa_ioc_s *ioc);  	void		(*ioc_reg_init)	(struct bfa_ioc_s *ioc);  	void		(*ioc_map_port)	(struct bfa_ioc_s *ioc);  	void		(*ioc_isr_mode_set)	(struct bfa_ioc_s *ioc,  					bfa_boolean_t msix); -	void		(*ioc_notify_hbfail)	(struct bfa_ioc_s *ioc); +	void		(*ioc_notify_fail)	(struct bfa_ioc_s *ioc);  	void		(*ioc_ownership_reset)	(struct bfa_ioc_s *ioc); +	bfa_boolean_t   (*ioc_sync_start)       (struct bfa_ioc_s *ioc); +	void		(*ioc_sync_join)	(struct bfa_ioc_s *ioc); +	void		(*ioc_sync_leave)	(struct bfa_ioc_s *ioc); +	void		(*ioc_sync_ack)		(struct bfa_ioc_s *ioc); +	bfa_boolean_t	(*ioc_sync_complete)	(struct bfa_ioc_s *ioc); +	bfa_boolean_t	(*ioc_lpu_read_stat)	(struct bfa_ioc_s *ioc); +	void		(*ioc_set_fwstate)	(struct bfa_ioc_s *ioc, +					enum bfi_ioc_state fwstate); +	enum bfi_ioc_state	(*ioc_get_fwstate)	(struct bfa_ioc_s *ioc); +	void		(*ioc_set_alt_fwstate)	(struct bfa_ioc_s *ioc, +					enum bfi_ioc_state fwstate); +	enum bfi_ioc_state	(*ioc_get_alt_fwstate)	(struct bfa_ioc_s *ioc); +}; + +/* + * Queue element to wait for room in request queue. FIFO order is + * maintained when fullfilling requests. + */ +struct bfa_reqq_wait_s { +	struct list_head	qe; +	void	(*qresume) (void *cbarg); +	void	*cbarg; +}; + +typedef void	(*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete); + +/* + * Generic BFA callback element. + */ +struct bfa_cb_qe_s { +	struct list_head	qe; +	bfa_cb_cbfn_t	cbfn; +	bfa_boolean_t	once; +	bfa_boolean_t	pre_rmv;	/* set for stack based qe(s) */ +	bfa_status_t	fw_status;	/* to access fw status in comp proc */ +	void		*cbarg; +}; + +/* + * IOCFC state machine definitions/declarations + */ +enum iocfc_event { +	IOCFC_E_INIT		= 1,	/* IOCFC init request		*/ +	IOCFC_E_START		= 2,	/* IOCFC mod start request	*/ +	IOCFC_E_STOP		= 3,	/* IOCFC stop request		*/ +	IOCFC_E_ENABLE		= 4,	/* IOCFC enable request		*/ +	IOCFC_E_DISABLE		= 5,	/* IOCFC disable request	*/ +	IOCFC_E_IOC_ENABLED	= 6,	/* IOC enabled message		*/ +	IOCFC_E_IOC_DISABLED	= 7,	/* IOC disabled message		*/ +	IOCFC_E_IOC_FAILED	= 8,	/* failure notice by IOC sm	*/ +	IOCFC_E_DCONF_DONE	= 9,	/* dconf read/write done	*/ +	IOCFC_E_CFG_DONE	= 10,	/* IOCFC config complete	*/ +}; + +/* + * ASIC block configurtion related + */ + +typedef void (*bfa_ablk_cbfn_t)(void *, enum bfa_status); + +struct bfa_ablk_s { +	struct bfa_ioc_s	*ioc; +	struct bfa_ablk_cfg_s	*cfg; +	u16			*pcifn; +	struct bfa_dma_s	dma_addr; +	bfa_boolean_t		busy; +	struct bfa_mbox_cmd_s	mb; +	bfa_ablk_cbfn_t		cbfn; +	void			*cbarg; +	struct bfa_ioc_notify_s	ioc_notify; +	struct bfa_mem_dma_s	ablk_dma; +}; +#define BFA_MEM_ABLK_DMA(__bfa)		(&((__bfa)->modules.ablk.ablk_dma)) + +/* + *	SFP module specific + */ +typedef void	(*bfa_cb_sfp_t) (void *cbarg, bfa_status_t status); + +struct bfa_sfp_s { +	void	*dev; +	struct bfa_ioc_s	*ioc; +	struct bfa_trc_mod_s	*trcmod; +	struct sfp_mem_s	*sfpmem; +	bfa_cb_sfp_t		cbfn; +	void			*cbarg; +	enum bfi_sfp_mem_e	memtype; /* mem access type   */ +	u32			status; +	struct bfa_mbox_cmd_s	mbcmd; +	u8			*dbuf_kva; /* dma buf virtual address */ +	u64			dbuf_pa;   /* dma buf physical address */ +	struct bfa_ioc_notify_s	ioc_notify; +	enum bfa_defs_sfp_media_e *media; +	enum bfa_port_speed	portspeed; +	bfa_cb_sfp_t		state_query_cbfn; +	void			*state_query_cbarg; +	u8			lock; +	u8			data_valid; /* data in dbuf is valid */ +	u8			state;	    /* sfp state  */ +	u8			state_query_lock; +	struct bfa_mem_dma_s	sfp_dma; +	u8			is_elb;	    /* eloopback  */ +}; + +#define BFA_SFP_MOD(__bfa)	(&(__bfa)->modules.sfp) +#define BFA_MEM_SFP_DMA(__bfa)	(&(BFA_SFP_MOD(__bfa)->sfp_dma)) + +u32	bfa_sfp_meminfo(void); + +void	bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, +			void *dev, struct bfa_trc_mod_s *trcmod); + +void	bfa_sfp_memclaim(struct bfa_sfp_s *diag, u8 *dm_kva, u64 dm_pa); +void	bfa_sfp_intr(void *bfaarg, struct bfi_mbmsg_s *msg); + +bfa_status_t	bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem, +			     bfa_cb_sfp_t cbfn, void *cbarg); + +bfa_status_t	bfa_sfp_media(struct bfa_sfp_s *sfp, +			enum bfa_defs_sfp_media_e *media, +			bfa_cb_sfp_t cbfn, void *cbarg); + +bfa_status_t	bfa_sfp_speed(struct bfa_sfp_s *sfp, +			enum bfa_port_speed portspeed, +			bfa_cb_sfp_t cbfn, void *cbarg); + +/* + *	Flash module specific + */ +typedef void	(*bfa_cb_flash_t) (void *cbarg, bfa_status_t status); + +struct bfa_flash_s { +	struct bfa_ioc_s *ioc;		/* back pointer to ioc */ +	struct bfa_trc_mod_s *trcmod; +	u32		type;           /* partition type */ +	u8		instance;       /* partition instance */ +	u8		rsv[3]; +	u32		op_busy;        /*  operation busy flag */ +	u32		residue;        /*  residual length */ +	u32		offset;         /*  offset */ +	bfa_status_t	status;         /*  status */ +	u8		*dbuf_kva;      /*  dma buf virtual address */ +	u64		dbuf_pa;        /*  dma buf physical address */ +	struct bfa_reqq_wait_s	reqq_wait; /*  to wait for room in reqq */ +	bfa_cb_flash_t	cbfn;           /*  user callback function */ +	void		*cbarg;         /*  user callback arg */ +	u8		*ubuf;          /*  user supplied buffer */ +	struct bfa_cb_qe_s	hcb_qe; /*  comp: BFA callback qelem */ +	u32		addr_off;       /*  partition address offset */ +	struct bfa_mbox_cmd_s	mb;       /*  mailbox */ +	struct bfa_ioc_notify_s	ioc_notify; /*  ioc event notify */ +	struct bfa_mem_dma_s	flash_dma; +}; + +#define BFA_FLASH(__bfa)		(&(__bfa)->modules.flash) +#define BFA_MEM_FLASH_DMA(__bfa)	(&(BFA_FLASH(__bfa)->flash_dma)) + +bfa_status_t bfa_flash_get_attr(struct bfa_flash_s *flash, +			struct bfa_flash_attr_s *attr, +			bfa_cb_flash_t cbfn, void *cbarg); +bfa_status_t bfa_flash_erase_part(struct bfa_flash_s *flash, +			enum bfa_flash_part_type type, u8 instance, +			bfa_cb_flash_t cbfn, void *cbarg); +bfa_status_t bfa_flash_update_part(struct bfa_flash_s *flash, +			enum bfa_flash_part_type type, u8 instance, +			void *buf, u32 len, u32 offset, +			bfa_cb_flash_t cbfn, void *cbarg); +bfa_status_t bfa_flash_read_part(struct bfa_flash_s *flash, +			enum bfa_flash_part_type type, u8 instance, void *buf, +			u32 len, u32 offset, bfa_cb_flash_t cbfn, void *cbarg); +u32	bfa_flash_meminfo(bfa_boolean_t mincfg); +void bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, +		void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg); +void bfa_flash_memclaim(struct bfa_flash_s *flash, +		u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg); +bfa_status_t    bfa_flash_raw_read(void __iomem *pci_bar_kva, +				u32 offset, char *buf, u32 len); + +/* + *	DIAG module specific + */ + +typedef void (*bfa_cb_diag_t) (void *cbarg, bfa_status_t status); +typedef void (*bfa_cb_diag_beacon_t) (void *dev, bfa_boolean_t beacon, +			bfa_boolean_t link_e2e_beacon); + +/* + *      Firmware ping test results + */ +struct bfa_diag_results_fwping { +	u32     data;   /* store the corrupted data */ +	u32     status; +	u32     dmastatus; +	u8      rsvd[4]; +}; + +struct bfa_diag_qtest_result_s { +	u32	status; +	u16	count;	/* successful queue test count */ +	u8	queue; +	u8	rsvd;	/* 64-bit align */ +}; + +/* + * Firmware ping test results + */ +struct bfa_diag_fwping_s { +	struct bfa_diag_results_fwping *result; +	bfa_cb_diag_t  cbfn; +	void            *cbarg; +	u32             data; +	u8              lock; +	u8              rsv[3]; +	u32             status; +	u32             count; +	struct bfa_mbox_cmd_s   mbcmd; +	u8              *dbuf_kva;      /* dma buf virtual address */ +	u64             dbuf_pa;        /* dma buf physical address */ +}; + +/* + *      Temperature sensor query results + */ +struct bfa_diag_results_tempsensor_s { +	u32     status; +	u16     temp;           /* 10-bit A/D value */ +	u16     brd_temp;       /* 9-bit board temp */ +	u8      ts_junc;        /* show junction tempsensor   */ +	u8      ts_brd;         /* show board tempsensor      */ +	u8      rsvd[6];        /* keep 8 bytes alignment     */ +}; + +struct bfa_diag_tsensor_s { +	bfa_cb_diag_t   cbfn; +	void            *cbarg; +	struct bfa_diag_results_tempsensor_s *temp; +	u8              lock; +	u8              rsv[3]; +	u32             status; +	struct bfa_mbox_cmd_s   mbcmd; +}; + +struct bfa_diag_sfpshow_s { +	struct sfp_mem_s        *sfpmem; +	bfa_cb_diag_t           cbfn; +	void                    *cbarg; +	u8      lock; +	u8      static_data; +	u8      rsv[2]; +	u32     status; +	struct bfa_mbox_cmd_s    mbcmd; +	u8      *dbuf_kva;      /* dma buf virtual address */ +	u64     dbuf_pa;        /* dma buf physical address */ +}; + +struct bfa_diag_led_s { +	struct bfa_mbox_cmd_s   mbcmd; +	bfa_boolean_t   lock;   /* 1: ledtest is operating */ +}; + +struct bfa_diag_beacon_s { +	struct bfa_mbox_cmd_s   mbcmd; +	bfa_boolean_t   state;          /* port beacon state */ +	bfa_boolean_t   link_e2e;       /* link beacon state */ +}; + +struct bfa_diag_s { +	void	*dev; +	struct bfa_ioc_s		*ioc; +	struct bfa_trc_mod_s		*trcmod; +	struct bfa_diag_fwping_s	fwping; +	struct bfa_diag_tsensor_s	tsensor; +	struct bfa_diag_sfpshow_s	sfpshow; +	struct bfa_diag_led_s		ledtest; +	struct bfa_diag_beacon_s	beacon; +	void	*result; +	struct bfa_timer_s timer; +	bfa_cb_diag_beacon_t  cbfn_beacon; +	bfa_cb_diag_t  cbfn; +	void		*cbarg; +	u8		block; +	u8		timer_active; +	u8		rsvd[2]; +	u32		status; +	struct bfa_ioc_notify_s	ioc_notify; +	struct bfa_mem_dma_s	diag_dma; +}; + +#define BFA_DIAG_MOD(__bfa)     (&(__bfa)->modules.diag_mod) +#define BFA_MEM_DIAG_DMA(__bfa) (&(BFA_DIAG_MOD(__bfa)->diag_dma)) + +u32	bfa_diag_meminfo(void); +void bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa); +void bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev, +		     bfa_cb_diag_beacon_t cbfn_beacon, +		     struct bfa_trc_mod_s *trcmod); +bfa_status_t	bfa_diag_reg_read(struct bfa_diag_s *diag, u32 offset, +			u32 len, u32 *buf, u32 force); +bfa_status_t	bfa_diag_reg_write(struct bfa_diag_s *diag, u32 offset, +			u32 len, u32 value, u32 force); +bfa_status_t	bfa_diag_tsensor_query(struct bfa_diag_s *diag, +			struct bfa_diag_results_tempsensor_s *result, +			bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, +			u32 pattern, struct bfa_diag_results_fwping *result, +			bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_diag_sfpshow(struct bfa_diag_s *diag, +			struct sfp_mem_s *sfpmem, u8 static_data, +			bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_diag_memtest(struct bfa_diag_s *diag, +			struct bfa_diag_memtest_s *memtest, u32 pattern, +			struct bfa_diag_memtest_result *result, +			bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_diag_ledtest(struct bfa_diag_s *diag, +			struct bfa_diag_ledtest_s *ledtest); +bfa_status_t	bfa_diag_beacon_port(struct bfa_diag_s *diag, +			bfa_boolean_t beacon, bfa_boolean_t link_e2e_beacon, +			u32 sec); + +/* + *	PHY module specific + */ +typedef void (*bfa_cb_phy_t) (void *cbarg, bfa_status_t status); + +struct bfa_phy_s { +	struct bfa_ioc_s *ioc;          /* back pointer to ioc */ +	struct bfa_trc_mod_s *trcmod;   /* trace module */ +	u8	instance;       /* port instance */ +	u8	op_busy;        /* operation busy flag */ +	u8	rsv[2]; +	u32	residue;        /* residual length */ +	u32	offset;         /* offset */ +	bfa_status_t	status;         /* status */ +	u8	*dbuf_kva;      /* dma buf virtual address */ +	u64	dbuf_pa;        /* dma buf physical address */ +	struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ +	bfa_cb_phy_t	cbfn;           /* user callback function */ +	void		*cbarg;         /* user callback arg */ +	u8		*ubuf;          /* user supplied buffer */ +	struct bfa_cb_qe_s	hcb_qe; /* comp: BFA callback qelem */ +	u32	addr_off;       /* phy address offset */ +	struct bfa_mbox_cmd_s	mb;       /* mailbox */ +	struct bfa_ioc_notify_s	ioc_notify; /* ioc event notify */ +	struct bfa_mem_dma_s	phy_dma; +}; +#define BFA_PHY(__bfa)	(&(__bfa)->modules.phy) +#define BFA_MEM_PHY_DMA(__bfa)	(&(BFA_PHY(__bfa)->phy_dma)) + +bfa_boolean_t bfa_phy_busy(struct bfa_ioc_s *ioc); +bfa_status_t bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance, +			struct bfa_phy_attr_s *attr, +			bfa_cb_phy_t cbfn, void *cbarg); +bfa_status_t bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance, +			struct bfa_phy_stats_s *stats, +			bfa_cb_phy_t cbfn, void *cbarg); +bfa_status_t bfa_phy_update(struct bfa_phy_s *phy, u8 instance, +			void *buf, u32 len, u32 offset, +			bfa_cb_phy_t cbfn, void *cbarg); +bfa_status_t bfa_phy_read(struct bfa_phy_s *phy, u8 instance, +			void *buf, u32 len, u32 offset, +			bfa_cb_phy_t cbfn, void *cbarg); + +u32	bfa_phy_meminfo(bfa_boolean_t mincfg); +void bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc, +		void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg); +void bfa_phy_memclaim(struct bfa_phy_s *phy, +		u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg); +void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg); + +/* + * FRU module specific + */ +typedef void (*bfa_cb_fru_t) (void *cbarg, bfa_status_t status); + +struct bfa_fru_s { +	struct bfa_ioc_s *ioc;		/* back pointer to ioc */ +	struct bfa_trc_mod_s *trcmod;	/* trace module */ +	u8		op_busy;	/* operation busy flag */ +	u8		rsv[3]; +	u32		residue;	/* residual length */ +	u32		offset;		/* offset */ +	bfa_status_t	status;		/* status */ +	u8		*dbuf_kva;	/* dma buf virtual address */ +	u64		dbuf_pa;	/* dma buf physical address */ +	struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ +	bfa_cb_fru_t	cbfn;		/* user callback function */ +	void		*cbarg;		/* user callback arg */ +	u8		*ubuf;		/* user supplied buffer */ +	struct bfa_cb_qe_s	hcb_qe;	/* comp: BFA callback qelem */ +	u32		addr_off;	/* fru address offset */ +	struct bfa_mbox_cmd_s mb;	/* mailbox */ +	struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */ +	struct bfa_mem_dma_s	fru_dma; +	u8		trfr_cmpl; +}; + +#define BFA_FRU(__bfa)	(&(__bfa)->modules.fru) +#define BFA_MEM_FRU_DMA(__bfa)	(&(BFA_FRU(__bfa)->fru_dma)) + +bfa_status_t bfa_fruvpd_update(struct bfa_fru_s *fru, +			void *buf, u32 len, u32 offset, +			bfa_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl); +bfa_status_t bfa_fruvpd_read(struct bfa_fru_s *fru, +			void *buf, u32 len, u32 offset, +			bfa_cb_fru_t cbfn, void *cbarg); +bfa_status_t bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size); +bfa_status_t bfa_tfru_write(struct bfa_fru_s *fru, +			void *buf, u32 len, u32 offset, +			bfa_cb_fru_t cbfn, void *cbarg); +bfa_status_t bfa_tfru_read(struct bfa_fru_s *fru, +			void *buf, u32 len, u32 offset, +			bfa_cb_fru_t cbfn, void *cbarg); +u32	bfa_fru_meminfo(bfa_boolean_t mincfg); +void bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, +		void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg); +void bfa_fru_memclaim(struct bfa_fru_s *fru, +		u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg); +void bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg); + +/* + * Driver Config( dconf) specific + */ +#define BFI_DCONF_SIGNATURE	0xabcdabcd +#define BFI_DCONF_VERSION	1 + +#pragma pack(1) +struct bfa_dconf_hdr_s { +	u32	signature; +	u32	version; +}; + +struct bfa_dconf_s { +	struct bfa_dconf_hdr_s		hdr; +	struct bfa_lunmask_cfg_s	lun_mask; +	struct bfa_throttle_cfg_s	throttle_cfg; +}; +#pragma pack() + +struct bfa_dconf_mod_s { +	bfa_sm_t		sm; +	u8			instance; +	bfa_boolean_t		read_data_valid; +	bfa_boolean_t		min_cfg; +	struct bfa_timer_s	timer; +	struct bfa_s		*bfa; +	void			*bfad; +	void			*trcmod; +	struct bfa_dconf_s	*dconf; +	struct bfa_mem_kva_s	kva_seg;  }; +#define BFA_DCONF_MOD(__bfa)	\ +	(&(__bfa)->modules.dconf_mod) +#define BFA_MEM_DCONF_KVA(__bfa)	(&(BFA_DCONF_MOD(__bfa)->kva_seg)) +#define bfa_dconf_read_data_valid(__bfa)	\ +	(BFA_DCONF_MOD(__bfa)->read_data_valid) +#define BFA_DCONF_UPDATE_TOV	5000	/* memtest timeout in msec */ +#define bfa_dconf_get_min_cfg(__bfa)	\ +	(BFA_DCONF_MOD(__bfa)->min_cfg) + +void	bfa_dconf_modinit(struct bfa_s *bfa); +void	bfa_dconf_modexit(struct bfa_s *bfa); +bfa_status_t	bfa_dconf_update(struct bfa_s *bfa); + +/* + *	IOC specfic macros + */  #define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)  #define bfa_ioc_devid(__ioc)		((__ioc)->pcidev.device_id)  #define bfa_ioc_bar0(__ioc)		((__ioc)->pcidev.pci_bar_kva)  #define bfa_ioc_portid(__ioc)		((__ioc)->port_id) +#define bfa_ioc_asic_gen(__ioc)		((__ioc)->asic_gen) +#define bfa_ioc_is_cna(__ioc)	\ +	((bfa_ioc_get_type(__ioc) == BFA_IOC_TYPE_FCoE) ||	\ +	 (bfa_ioc_get_type(__ioc) == BFA_IOC_TYPE_LL))  #define bfa_ioc_fetch_stats(__ioc, __stats) \  		(((__stats)->drv_stats) = (__ioc)->stats)  #define bfa_ioc_clr_stats(__ioc)	\ @@ -269,18 +822,16 @@ struct bfa_ioc_hwif_s {  #define bfa_ioc_maxfrsize(__ioc)	((__ioc)->attr->maxfrsize)  #define bfa_ioc_rx_bbcredit(__ioc)	((__ioc)->attr->rx_bbcredit)  #define bfa_ioc_speed_sup(__ioc)	\ -	BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop) +	((bfa_ioc_is_cna(__ioc)) ? BFA_PORT_SPEED_10GBPS :	\ +	 BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop))  #define bfa_ioc_get_nports(__ioc)	\  	BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)  #define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)  #define BFA_IOC_FWIMG_MINSZ	(16 * 1024) -#define BFA_IOC_FWIMG_TYPE(__ioc)					\ -	(((__ioc)->ctdev) ?						\ -	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :	\ -	 BFI_IMAGE_CB_FC) -#define BFA_IOC_FW_SMEM_SIZE(__ioc)					\ -	(((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE) +#define BFA_IOC_FW_SMEM_SIZE(__ioc)			\ +	((bfa_ioc_asic_gen(__ioc) == BFI_ASIC_GEN_CB)	\ +	 ? BFI_SMEM_CB_SIZE : BFI_SMEM_CT_SIZE)  #define BFA_IOC_FLASH_CHUNK_NO(off)		(off / BFI_FLASH_CHUNK_SZ_WORDS)  #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)	(off % BFI_FLASH_CHUNK_SZ_WORDS)  #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno)  (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) @@ -293,7 +844,7 @@ void bfa_ioc_mbox_register(struct bfa_ioc_s *ioc,  		bfa_ioc_mbox_mcfunc_t *mcfuncs);  void bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc);  void bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len); -void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg); +bfa_boolean_t bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);  void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,  		bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg); @@ -303,43 +854,53 @@ void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,  #define bfa_ioc_pll_init_asic(__ioc) \  	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \ -			   (__ioc)->fcmode)) +			   (__ioc)->asic_mode))  bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc); -bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode); -bfa_boolean_t bfa_ioc_ct_pll_init_complete(void __iomem *rb); -bfa_status_t bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode); +bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode mode); +bfa_status_t bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode); +bfa_status_t bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode); -#define	bfa_ioc_isr_mode_set(__ioc, __msix)			\ -			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix)) +#define bfa_ioc_isr_mode_set(__ioc, __msix) do {			\ +	if ((__ioc)->ioc_hwif->ioc_isr_mode_set)			\ +		((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix));	\ +} while (0)  #define	bfa_ioc_ownership_reset(__ioc)				\  			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc)) +#define bfa_ioc_get_fcmode(__ioc)	((__ioc)->fcmode) +#define bfa_ioc_lpu_read_stat(__ioc) do {			\ +	if ((__ioc)->ioc_hwif->ioc_lpu_read_stat)		\ +		((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc));	\ +} while (0) - -void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);  void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc); +void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc); +void bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc); +void bfa_ioc_ct2_poweron(struct bfa_ioc_s *ioc);  void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,  		struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);  void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);  void bfa_ioc_detach(struct bfa_ioc_s *ioc); +void bfa_ioc_suspend(struct bfa_ioc_s *ioc);  void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, -		enum bfi_mclass mc); -u32 bfa_ioc_meminfo(void); +		enum bfi_pcifn_class clscode);  void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa);  void bfa_ioc_enable(struct bfa_ioc_s *ioc);  void bfa_ioc_disable(struct bfa_ioc_s *ioc);  bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc); -void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, -		u32 boot_param); +bfa_status_t bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, +		u32 boot_env);  void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);  void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);  bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);  bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc);  bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc); +bfa_boolean_t bfa_ioc_is_acq_addr(struct bfa_ioc_s *ioc);  bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);  bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc); +void bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc);  enum bfa_ioc_type_e bfa_ioc_get_type(struct bfa_ioc_s *ioc);  void bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num);  void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver); @@ -353,89 +914,120 @@ enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc_s *ioc);  void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr);  void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,  		struct bfa_adapter_attr_s *ad_attr); -int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover);  void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave);  bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata,  		int *trclen); -void bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc);  bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,  				 int *trclen);  bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,  	u32 *offset, int *buflen); -u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr); -u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr); -void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc); -bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc); -void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc, -	struct bfa_ioc_hbfail_notify_s *notify); +bfa_status_t bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc);  bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg); -void bfa_ioc_sem_release(void __iomem *sem_reg); -void bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc);  void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,  			struct bfi_ioc_image_hdr_s *fwhdr);  bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,  			struct bfi_ioc_image_hdr_s *fwhdr); +void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event);  bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);  bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc); +void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);  /* + * asic block configuration related APIs + */ +u32	bfa_ablk_meminfo(void); +void bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa); +void bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc); +bfa_status_t bfa_ablk_query(struct bfa_ablk_s *ablk, +		struct bfa_ablk_cfg_s *ablk_cfg, +		bfa_ablk_cbfn_t cbfn, void *cbarg); +bfa_status_t bfa_ablk_adapter_config(struct bfa_ablk_s *ablk, +		enum bfa_mode_s mode, int max_pf, int max_vf, +		bfa_ablk_cbfn_t cbfn, void *cbarg); +bfa_status_t bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, +		enum bfa_mode_s mode, int max_pf, int max_vf, +		bfa_ablk_cbfn_t cbfn, void *cbarg); +bfa_status_t bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn, +		u8 port, enum bfi_pcifn_class personality, +		u16 bw_min, u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg); +bfa_status_t bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn, +		bfa_ablk_cbfn_t cbfn, void *cbarg); +bfa_status_t bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, +		u16 bw_min, u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg); +bfa_status_t bfa_ablk_optrom_en(struct bfa_ablk_s *ablk, +		bfa_ablk_cbfn_t cbfn, void *cbarg); +bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, +		bfa_ablk_cbfn_t cbfn, void *cbarg); + +bfa_status_t bfa_ioc_flash_img_get_chnk(struct bfa_ioc_s *ioc, u32 off, +				u32 *fwimg); +/*   * bfa mfg wwn API functions   */ -wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc); -wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc);  mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc); -wwn_t bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc); -wwn_t bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc);  mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc); -u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);  /*   * F/W Image Size & Chunk   */ -extern u32 bfi_image_ct_fc_size; -extern u32 bfi_image_ct_cna_size; -extern u32 bfi_image_cb_fc_size; -extern u32 *bfi_image_ct_fc; -extern u32 *bfi_image_ct_cna; -extern u32 *bfi_image_cb_fc; +extern u32 bfi_image_cb_size; +extern u32 bfi_image_ct_size; +extern u32 bfi_image_ct2_size; +extern u32 *bfi_image_cb; +extern u32 *bfi_image_ct; +extern u32 *bfi_image_ct2;  static inline u32 * -bfi_image_ct_fc_get_chunk(u32 off) -{	return (u32 *)(bfi_image_ct_fc + off); } +bfi_image_cb_get_chunk(u32 off) +{ +	return (u32 *)(bfi_image_cb + off); +}  static inline u32 * -bfi_image_ct_cna_get_chunk(u32 off) -{	return (u32 *)(bfi_image_ct_cna + off); } +bfi_image_ct_get_chunk(u32 off) +{ +	return (u32 *)(bfi_image_ct + off); +}  static inline u32 * -bfi_image_cb_fc_get_chunk(u32 off) -{	return (u32 *)(bfi_image_cb_fc + off); } +bfi_image_ct2_get_chunk(u32 off) +{ +	return (u32 *)(bfi_image_ct2 + off); +}  static inline u32* -bfa_cb_image_get_chunk(int type, u32 off) +bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off)  { -	switch (type) { -	case BFI_IMAGE_CT_FC: -		return bfi_image_ct_fc_get_chunk(off);	break; -	case BFI_IMAGE_CT_CNA: -		return bfi_image_ct_cna_get_chunk(off);	break; -	case BFI_IMAGE_CB_FC: -		return bfi_image_cb_fc_get_chunk(off);	break; -	default: return 0; +	switch (asic_gen) { +	case BFI_ASIC_GEN_CB: +		return bfi_image_cb_get_chunk(off); +		break; +	case BFI_ASIC_GEN_CT: +		return bfi_image_ct_get_chunk(off); +		break; +	case BFI_ASIC_GEN_CT2: +		return bfi_image_ct2_get_chunk(off); +		break; +	default: +		return NULL;  	}  }  static inline u32 -bfa_cb_image_get_size(int type) +bfa_cb_image_get_size(enum bfi_asic_gen asic_gen)  { -	switch (type) { -	case BFI_IMAGE_CT_FC: -		return bfi_image_ct_fc_size;	break; -	case BFI_IMAGE_CT_CNA: -		return bfi_image_ct_cna_size;	break; -	case BFI_IMAGE_CB_FC: -		return bfi_image_cb_fc_size;	break; -	default: return 0; +	switch (asic_gen) { +	case BFI_ASIC_GEN_CB: +		return bfi_image_cb_size; +		break; +	case BFI_ASIC_GEN_CT: +		return bfi_image_ct_size; +		break; +	case BFI_ASIC_GEN_CT2: +		return bfi_image_ct2_size; +		break; +	default: +		return 0;  	}  } diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index 90994504385..453c2f5b556 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -15,12 +15,15 @@   * General Public License for more details.   */ +#include "bfad_drv.h"  #include "bfa_ioc.h" -#include "bfi_cbreg.h" +#include "bfi_reg.h"  #include "bfa_defs.h"  BFA_TRC_FILE(CNA, IOC_CB); +#define bfa_ioc_cb_join_pos(__ioc) ((u32) (1 << BFA_IOC_CB_JOIN_SH)) +  /*   * forward declarations   */ @@ -29,10 +32,21 @@ static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc);  static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);  static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc);  static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); -static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc);  static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); - -struct bfa_ioc_hwif_s hwif_cb; +static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); +static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_set_cur_ioc_fwstate( +			struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_set_alt_ioc_fwstate( +			struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc); + +static struct bfa_ioc_hwif_s hwif_cb;  /*   * Called from bfa_ioc_attach() to map asic specific calls. @@ -46,8 +60,17 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)  	hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init;  	hwif_cb.ioc_map_port = bfa_ioc_cb_map_port;  	hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; -	hwif_cb.ioc_notify_hbfail = bfa_ioc_cb_notify_hbfail; +	hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail;  	hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; +	hwif_cb.ioc_sync_start = bfa_ioc_cb_sync_start; +	hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; +	hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; +	hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; +	hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete; +	hwif_cb.ioc_set_fwstate = bfa_ioc_cb_set_cur_ioc_fwstate; +	hwif_cb.ioc_get_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate; +	hwif_cb.ioc_set_alt_fwstate = bfa_ioc_cb_set_alt_ioc_fwstate; +	hwif_cb.ioc_get_alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate;  	ioc->ioc_hwif = &hwif_cb;  } @@ -58,6 +81,29 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)  static bfa_boolean_t  bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)  { +	enum bfi_ioc_state alt_fwstate, cur_fwstate; +	struct bfi_ioc_image_hdr_s fwhdr; + +	cur_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc); +	bfa_trc(ioc, cur_fwstate); +	alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc); +	bfa_trc(ioc, alt_fwstate); + +	/* +	 * Uninit implies this is the only driver as of now. +	 */ +	if (cur_fwstate == BFI_IOC_UNINIT) +		return BFA_TRUE; +	/* +	 * Check if another driver with a different firmware is active +	 */ +	bfa_ioc_fwver_get(ioc, &fwhdr); +	if (!bfa_ioc_fwver_cmp(ioc, &fwhdr) && +		alt_fwstate != BFI_IOC_DISABLED) { +		bfa_trc(ioc, alt_fwstate); +		return BFA_FALSE; +	} +  	return BFA_TRUE;  } @@ -70,9 +116,9 @@ bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)   * Notify other functions on HB failure.   */  static void -bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc) +bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)  { -	writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); +	writel(~0U, ioc->ioc_regs.err_set);  	readl(ioc->ioc_regs.err_set);  } @@ -108,9 +154,11 @@ bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)  	if (ioc->port_id == 0) {  		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;  		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; +		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;  	} else {  		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);  		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); +		ioc->ioc_regs.alt_ioc_fwstate = (rb + BFA_IOC0_STATE_REG);  	}  	/* @@ -124,8 +172,8 @@ bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)  	 */  	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);  	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); -	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_400_CTL_REG); -	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_212_CTL_REG); +	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG); +	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);  	/*  	 * IOC semaphore registers and serialization @@ -169,6 +217,29 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)  }  /* + * Synchronized IOC failure processing routines + */ +static bfa_boolean_t +bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc) +{ +	u32 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); + +	/** +	 * Driver load time.  If the join bit is set, +	 * it is due to an unclean exit by the driver for this +	 * PCI fn in the previous incarnation. Whoever comes here first +	 * should clean it up, no matter which PCI fn. +	 */ +	if (ioc_fwstate & BFA_IOC_CB_JOIN_MASK) { +		writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); +		writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); +		return BFA_TRUE; +	} + +	return bfa_ioc_cb_sync_complete(ioc); +} + +/*   * Cleanup hw semaphore and usecnt registers   */  static void @@ -181,50 +252,157 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)  	 * will lock it instead of clearing it.  	 */  	readl(ioc->ioc_regs.ioc_sem_reg); -	bfa_ioc_hw_sem_release(ioc); +	writel(1, ioc->ioc_regs.ioc_sem_reg);  } +/* + * Synchronized IOC failure processing routines + */ +static void +bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc) +{ +	u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); +	u32 join_pos = bfa_ioc_cb_join_pos(ioc); + +	writel((r32 | join_pos), ioc->ioc_regs.ioc_fwstate); +} +static void +bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc) +{ +	u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); +	u32 join_pos = bfa_ioc_cb_join_pos(ioc); + +	writel((r32 & ~join_pos), ioc->ioc_regs.ioc_fwstate); +} + +static void +bfa_ioc_cb_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc, +			enum bfi_ioc_state fwstate) +{ +	u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); + +	writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)), +				ioc->ioc_regs.ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_cb_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc) +{ +	return (enum bfi_ioc_state)(readl(ioc->ioc_regs.ioc_fwstate) & +			BFA_IOC_CB_FWSTATE_MASK); +} + +static void +bfa_ioc_cb_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc, +			enum bfi_ioc_state fwstate) +{ +	u32 r32 = readl(ioc->ioc_regs.alt_ioc_fwstate); + +	writel((fwstate | (r32 & BFA_IOC_CB_JOIN_MASK)), +				ioc->ioc_regs.alt_ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_cb_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc) +{ +	return (enum bfi_ioc_state)(readl(ioc->ioc_regs.alt_ioc_fwstate) & +			BFA_IOC_CB_FWSTATE_MASK); +} + +static void +bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc) +{ +	bfa_ioc_cb_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); +} + +static bfa_boolean_t +bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc) +{ +	u32 fwstate, alt_fwstate; +	fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc); + +	/* +	 * At this point, this IOC is hoding the hw sem in the +	 * start path (fwcheck) OR in the disable/enable path +	 * OR to check if the other IOC has acknowledged failure. +	 * +	 * So, this IOC can be in UNINIT, INITING, DISABLED, FAIL +	 * or in MEMTEST states. In a normal scenario, this IOC +	 * can not be in OP state when this function is called. +	 * +	 * However, this IOC could still be in OP state when +	 * the OS driver is starting up, if the OptROM code has +	 * left it in that state. +	 * +	 * If we had marked this IOC's fwstate as BFI_IOC_FAIL +	 * in the failure case and now, if the fwstate is not +	 * BFI_IOC_FAIL it implies that the other PCI fn have +	 * reinitialized the ASIC or this IOC got disabled, so +	 * return TRUE. +	 */ +	if (fwstate == BFI_IOC_UNINIT || +		fwstate == BFI_IOC_INITING || +		fwstate == BFI_IOC_DISABLED || +		fwstate == BFI_IOC_MEMTEST || +		fwstate == BFI_IOC_OP) +		return BFA_TRUE; +	else { +		alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc); +		if (alt_fwstate == BFI_IOC_FAIL || +			alt_fwstate == BFI_IOC_DISABLED || +			alt_fwstate == BFI_IOC_UNINIT || +			alt_fwstate == BFI_IOC_INITING || +			alt_fwstate == BFI_IOC_MEMTEST) +			return BFA_TRUE; +		else +			return BFA_FALSE; +	} +}  bfa_status_t -bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode) -{ -	u32	pll_sclk, pll_fclk; - -	pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN | -		__APP_PLL_212_P0_1(3U) | -		__APP_PLL_212_JITLMT0_1(3U) | -		__APP_PLL_212_CNTLMT0_1(3U); -	pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN | -		__APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) | -		__APP_PLL_400_JITLMT0_1(3U) | -		__APP_PLL_400_CNTLMT0_1(3U); -	writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG)); -	writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG)); +bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode) +{ +	u32	pll_sclk, pll_fclk, join_bits; + +	pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN | +		__APP_PLL_SCLK_P0_1(3U) | +		__APP_PLL_SCLK_JITLMT0_1(3U) | +		__APP_PLL_SCLK_CNTLMT0_1(3U); +	pll_fclk = __APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN | +		__APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) | +		__APP_PLL_LCLK_JITLMT0_1(3U) | +		__APP_PLL_LCLK_CNTLMT0_1(3U); +	join_bits = readl(rb + BFA_IOC0_STATE_REG) & +			BFA_IOC_CB_JOIN_MASK; +	writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC0_STATE_REG)); +	join_bits = readl(rb + BFA_IOC1_STATE_REG) & +			BFA_IOC_CB_JOIN_MASK; +	writel((BFI_IOC_UNINIT | join_bits), (rb + BFA_IOC1_STATE_REG));  	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));  	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));  	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));  	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));  	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));  	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); -	writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG); -	writel(__APP_PLL_212_BYPASS | __APP_PLL_212_LOGIC_SOFT_RESET, -			rb + APP_PLL_212_CTL_REG); -	writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG); -	writel(__APP_PLL_400_BYPASS | __APP_PLL_400_LOGIC_SOFT_RESET, -			rb + APP_PLL_400_CTL_REG); +	writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG); +	writel(__APP_PLL_SCLK_BYPASS | __APP_PLL_SCLK_LOGIC_SOFT_RESET, +			rb + APP_PLL_SCLK_CTL_REG); +	writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG); +	writel(__APP_PLL_LCLK_BYPASS | __APP_PLL_LCLK_LOGIC_SOFT_RESET, +			rb + APP_PLL_LCLK_CTL_REG);  	udelay(2); -	writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG); -	writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG); -	writel(pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET, -			rb + APP_PLL_212_CTL_REG); -	writel(pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET, -			rb + APP_PLL_400_CTL_REG); +	writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG); +	writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG); +	writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET, +			rb + APP_PLL_SCLK_CTL_REG); +	writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET, +			rb + APP_PLL_LCLK_CTL_REG);  	udelay(2000);  	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));  	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); -	writel(pll_sclk, (rb + APP_PLL_212_CTL_REG)); -	writel(pll_fclk, (rb + APP_PLL_400_CTL_REG)); +	writel(pll_sclk, (rb + APP_PLL_SCLK_CTL_REG)); +	writel(pll_fclk, (rb + APP_PLL_LCLK_CTL_REG));  	return BFA_STATUS_OK;  } diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 115730c0aa7..bd53150e4ee 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -15,42 +15,43 @@   * General Public License for more details.   */ +#include "bfad_drv.h"  #include "bfa_ioc.h" -#include "bfi_ctreg.h" +#include "bfi_reg.h"  #include "bfa_defs.h"  BFA_TRC_FILE(CNA, IOC_CT); +#define bfa_ioc_ct_sync_pos(__ioc)      \ +		((uint32_t) (1 << bfa_ioc_pcifn(__ioc))) +#define BFA_IOC_SYNC_REQD_SH    16 +#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff) +#define bfa_ioc_ct_clear_sync_ackd(__val)       (__val & 0xffff0000) +#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH) +#define bfa_ioc_ct_sync_reqd_pos(__ioc) \ +			(bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH) +  /*   * forward declarations   */  static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);  static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc); -static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc); -static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); -static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); -static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc);  static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); - -struct bfa_ioc_hwif_s hwif_ct; - -/* - * Called from bfa_ioc_attach() to map asic specific calls. - */ -void -bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) -{ -	hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; -	hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock; -	hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; -	hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; -	hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; -	hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; -	hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; -	hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; - -	ioc->ioc_hwif = &hwif_ct; -} +static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); +static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_set_cur_ioc_fwstate( +			struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_set_alt_ioc_fwstate( +			struct bfa_ioc_s *ioc, enum bfi_ioc_state fwstate); +static enum bfi_ioc_state bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc); + +static struct bfa_ioc_hwif_s hwif_ct; +static struct bfa_ioc_hwif_s hwif_ct2;  /*   * Return true if firmware of current driver matches the running firmware. @@ -62,19 +63,6 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)  	u32 usecnt;  	struct bfi_ioc_image_hdr_s fwhdr; -	/* -	 * Firmware match check is relevant only for CNA. -	 */ -	if (!ioc->cna) -		return BFA_TRUE; - -	/* -	 * If bios boot (flash based) -- do not increment usage count -	 */ -	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < -						BFA_IOC_FWIMG_MINSZ) -		return BFA_TRUE; -  	bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);  	usecnt = readl(ioc->ioc_regs.ioc_usage_reg); @@ -83,7 +71,9 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)  	 */  	if (usecnt == 0) {  		writel(1, ioc->ioc_regs.ioc_usage_reg); -		bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); +		readl(ioc->ioc_regs.ioc_usage_sem_reg); +		writel(1, ioc->ioc_regs.ioc_usage_sem_reg); +		writel(0, ioc->ioc_regs.ioc_fail_sync);  		bfa_trc(ioc, usecnt);  		return BFA_TRUE;  	} @@ -94,14 +84,15 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)  	/*  	 * Use count cannot be non-zero and chip in uninitialized state.  	 */ -	bfa_assert(ioc_fwstate != BFI_IOC_UNINIT); +	WARN_ON(ioc_fwstate == BFI_IOC_UNINIT);  	/*  	 * Check if another driver with a different firmware is active  	 */  	bfa_ioc_fwver_get(ioc, &fwhdr);  	if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { -		bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); +		readl(ioc->ioc_regs.ioc_usage_sem_reg); +		writel(1, ioc->ioc_regs.ioc_usage_sem_reg);  		bfa_trc(ioc, usecnt);  		return BFA_FALSE;  	} @@ -111,7 +102,8 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)  	 */  	usecnt++;  	writel(usecnt, ioc->ioc_regs.ioc_usage_reg); -	bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); +	readl(ioc->ioc_regs.ioc_usage_sem_reg); +	writel(1, ioc->ioc_regs.ioc_usage_sem_reg);  	bfa_trc(ioc, usecnt);  	return BFA_TRUE;  } @@ -122,44 +114,34 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)  	u32 usecnt;  	/* -	 * Firmware lock is relevant only for CNA. -	 */ -	if (!ioc->cna) -		return; - -	/* -	 * If bios boot (flash based) -- do not decrement usage count -	 */ -	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < -						BFA_IOC_FWIMG_MINSZ) -		return; - -	/*  	 * decrement usage count  	 */  	bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);  	usecnt = readl(ioc->ioc_regs.ioc_usage_reg); -	bfa_assert(usecnt > 0); +	WARN_ON(usecnt <= 0);  	usecnt--;  	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);  	bfa_trc(ioc, usecnt); -	bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); +	readl(ioc->ioc_regs.ioc_usage_sem_reg); +	writel(1, ioc->ioc_regs.ioc_usage_sem_reg);  }  /*   * Notify other functions on HB failure.   */  static void -bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc) +bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)  { -	if (ioc->cna) { +	if (bfa_ioc_is_cna(ioc)) {  		writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); +		writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);  		/* Wait for halt to take effect */  		readl(ioc->ioc_regs.ll_halt); +		readl(ioc->ioc_regs.alt_ll_halt);  	} else { -		writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); +		writel(~0U, ioc->ioc_regs.err_set);  		readl(ioc->ioc_regs.err_set);  	}  } @@ -167,7 +149,7 @@ bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc)  /*   * Host to LPU mailbox message addresses   */ -static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { +static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } ct_fnreg[] = {  	{ HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },  	{ HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },  	{ HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 }, @@ -177,21 +159,31 @@ static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {  /*   * Host <-> LPU mailbox command/status registers - port 0   */ -static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = { -	{ HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT }, -	{ HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT }, -	{ HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT }, -	{ HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT } +static struct { u32 hfn, lpu; } ct_p0reg[] = { +	{ HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT }, +	{ HOSTFN1_LPU0_CMD_STAT, LPU0_HOSTFN1_CMD_STAT }, +	{ HOSTFN2_LPU0_CMD_STAT, LPU0_HOSTFN2_CMD_STAT }, +	{ HOSTFN3_LPU0_CMD_STAT, LPU0_HOSTFN3_CMD_STAT }  };  /*   * Host <-> LPU mailbox command/status registers - port 1   */ -static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = { -	{ HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT }, -	{ HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT }, -	{ HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT }, -	{ HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT } +static struct { u32 hfn, lpu; } ct_p1reg[] = { +	{ HOSTFN0_LPU1_CMD_STAT, LPU1_HOSTFN0_CMD_STAT }, +	{ HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }, +	{ HOSTFN2_LPU1_CMD_STAT, LPU1_HOSTFN2_CMD_STAT }, +	{ HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT } +}; + +static struct { uint32_t hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu, lpu_read; } +	ct2_reg[] = { +	{ CT2_HOSTFN_LPU0_MBOX0, CT2_LPU0_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM, +	  CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT, +	  CT2_HOSTFN_LPU0_READ_STAT}, +	{ CT2_HOSTFN_LPU1_MBOX0, CT2_LPU1_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM, +	  CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT, +	  CT2_HOSTFN_LPU1_READ_STAT},  };  static void @@ -202,22 +194,26 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)  	rb = bfa_ioc_bar0(ioc); -	ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; -	ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; -	ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; +	ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox; +	ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox; +	ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn;  	if (ioc->port_id == 0) {  		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;  		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; -		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; -		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; +		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG; +		ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p0reg[pcifn].hfn; +		ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p0reg[pcifn].lpu;  		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; +		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;  	} else {  		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);  		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); -		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; -		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; +		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG; +		ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p1reg[pcifn].hfn; +		ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p1reg[pcifn].lpu;  		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; +		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;  	}  	/* @@ -225,8 +221,8 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)  	 */  	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);  	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); -	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG); -	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG); +	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG); +	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);  	/*  	 * IOC semaphore registers and serialization @@ -235,6 +231,65 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)  	ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);  	ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);  	ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT); +	ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC); + +	/* +	 * sram memory access +	 */ +	ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); +	ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; + +	/* +	 * err set reg : for notification of hb failure in fcmode +	 */ +	ioc->ioc_regs.err_set = (rb + ERR_SET_REG); +} + +static void +bfa_ioc_ct2_reg_init(struct bfa_ioc_s *ioc) +{ +	void __iomem *rb; +	int	port = bfa_ioc_portid(ioc); + +	rb = bfa_ioc_bar0(ioc); + +	ioc->ioc_regs.hfn_mbox = rb + ct2_reg[port].hfn_mbox; +	ioc->ioc_regs.lpu_mbox = rb + ct2_reg[port].lpu_mbox; +	ioc->ioc_regs.host_page_num_fn = rb + ct2_reg[port].hfn_pgn; +	ioc->ioc_regs.hfn_mbox_cmd = rb + ct2_reg[port].hfn; +	ioc->ioc_regs.lpu_mbox_cmd = rb + ct2_reg[port].lpu; +	ioc->ioc_regs.lpu_read_stat = rb + ct2_reg[port].lpu_read; + +	if (port == 0) { +		ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC0_HBEAT_REG; +		ioc->ioc_regs.ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG; +		ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC1_STATE_REG; +		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; +		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1; +	} else { +		ioc->ioc_regs.heartbeat = (rb + CT2_BFA_IOC1_HBEAT_REG); +		ioc->ioc_regs.ioc_fwstate = (rb + CT2_BFA_IOC1_STATE_REG); +		ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG; +		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; +		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0; +	} + +	/* +	 * PSS control registers +	 */ +	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); +	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG); +	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + CT2_APP_PLL_LCLK_CTL_REG); +	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + CT2_APP_PLL_SCLK_CTL_REG); + +	/* +	 * IOC semaphore registers and serialization +	 */ +	ioc->ioc_regs.ioc_sem_reg = (rb + CT2_HOST_SEM0_REG); +	ioc->ioc_regs.ioc_usage_sem_reg = (rb + CT2_HOST_SEM1_REG); +	ioc->ioc_regs.ioc_init_sem_reg = (rb + CT2_HOST_SEM2_REG); +	ioc->ioc_regs.ioc_usage_reg = (rb + CT2_BFA_FW_USE_COUNT); +	ioc->ioc_regs.ioc_fail_sync = (rb + CT2_BFA_IOC_FAIL_SYNC);  	/*  	 * sram memory access @@ -270,6 +325,19 @@ bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc)  	bfa_trc(ioc, ioc->port_id);  } +static void +bfa_ioc_ct2_map_port(struct bfa_ioc_s *ioc) +{ +	void __iomem	*rb = ioc->pcidev.pci_bar_kva; +	u32	r32; + +	r32 = readl(rb + CT2_HOSTFN_PERSONALITY0); +	ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH); + +	bfa_trc(ioc, bfa_ioc_pcifn(ioc)); +	bfa_trc(ioc, ioc->port_id); +} +  /*   * Set interrupt mode for a function: INTX or MSIX   */ @@ -288,7 +356,7 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)  	/*  	 * If already in desired mode, do not change anything  	 */ -	if (!msix && mode) +	if ((!msix && mode) || (msix && !mode))  		return;  	if (msix) @@ -303,6 +371,20 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)  	writel(r32, rb + FNC_PERS_REG);  } +bfa_boolean_t +bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc_s *ioc) +{ +	u32	r32; + +	r32 = readl(ioc->ioc_regs.lpu_read_stat); +	if (r32) { +		writel(1, ioc->ioc_regs.lpu_read_stat); +		return BFA_TRUE; +	} + +	return BFA_FALSE; +} +  /*   * Cleanup hw semaphore and usecnt registers   */ @@ -310,49 +392,214 @@ static void  bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)  { -	if (ioc->cna) { -		bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); -		writel(0, ioc->ioc_regs.ioc_usage_reg); -		bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); -	} +	bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); +	writel(0, ioc->ioc_regs.ioc_usage_reg); +	readl(ioc->ioc_regs.ioc_usage_sem_reg); +	writel(1, ioc->ioc_regs.ioc_usage_sem_reg); +	writel(0, ioc->ioc_regs.ioc_fail_sync);  	/*  	 * Read the hw sem reg to make sure that it is locked  	 * before we clear it. If it is not locked, writing 1  	 * will lock it instead of clearing it.  	 */  	readl(ioc->ioc_regs.ioc_sem_reg); -	bfa_ioc_hw_sem_release(ioc); +	writel(1, ioc->ioc_regs.ioc_sem_reg);  } +static bfa_boolean_t +bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc) +{ +	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); +	uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); + +	/* +	 * Driver load time.  If the sync required bit for this PCI fn +	 * is set, it is due to an unclean exit by the driver for this +	 * PCI fn in the previous incarnation. Whoever comes here first +	 * should clean it up, no matter which PCI fn. +	 */ + +	if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) { +		writel(0, ioc->ioc_regs.ioc_fail_sync); +		writel(1, ioc->ioc_regs.ioc_usage_reg); +		writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); +		writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); +		return BFA_TRUE; +	} +	return bfa_ioc_ct_sync_complete(ioc); +}  /* - * Check the firmware state to know if pll_init has been completed already + * Synchronized IOC failure processing routines   */ -bfa_boolean_t -bfa_ioc_ct_pll_init_complete(void __iomem *rb) +static void +bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc)  { -	if ((readl(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) || -	  (readl(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP)) +	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); +	uint32_t sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc); + +	writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync); +} + +static void +bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc) +{ +	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); +	uint32_t sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) | +					bfa_ioc_ct_sync_pos(ioc); + +	writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync); +} + +static void +bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc) +{ +	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); + +	writel((r32 | bfa_ioc_ct_sync_pos(ioc)), +		ioc->ioc_regs.ioc_fail_sync); +} + +static bfa_boolean_t +bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc) +{ +	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); +	uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); +	uint32_t sync_ackd = bfa_ioc_ct_get_sync_ackd(r32); +	uint32_t tmp_ackd; + +	if (sync_ackd == 0)  		return BFA_TRUE; +	/* +	 * The check below is to see whether any other PCI fn +	 * has reinitialized the ASIC (reset sync_ackd bits) +	 * and failed again while this IOC was waiting for hw +	 * semaphore (in bfa_iocpf_sm_semwait()). +	 */ +	tmp_ackd = sync_ackd; +	if ((sync_reqd &  bfa_ioc_ct_sync_pos(ioc)) && +		!(sync_ackd & bfa_ioc_ct_sync_pos(ioc))) +		sync_ackd |= bfa_ioc_ct_sync_pos(ioc); + +	if (sync_reqd == sync_ackd) { +		writel(bfa_ioc_ct_clear_sync_ackd(r32), +			ioc->ioc_regs.ioc_fail_sync); +		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); +		writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate); +		return BFA_TRUE; +	} + +	/* +	 * If another PCI fn reinitialized and failed again while +	 * this IOC was waiting for hw sem, the sync_ackd bit for +	 * this IOC need to be set again to allow reinitialization. +	 */ +	if (tmp_ackd != sync_ackd) +		writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync); +  	return BFA_FALSE;  } +/** + * Called from bfa_ioc_attach() to map asic specific calls. + */ +static void +bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif) +{ +	hwif->ioc_firmware_lock = bfa_ioc_ct_firmware_lock; +	hwif->ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock; +	hwif->ioc_notify_fail = bfa_ioc_ct_notify_fail; +	hwif->ioc_ownership_reset = bfa_ioc_ct_ownership_reset; +	hwif->ioc_sync_start = bfa_ioc_ct_sync_start; +	hwif->ioc_sync_join = bfa_ioc_ct_sync_join; +	hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave; +	hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack; +	hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete; +	hwif->ioc_set_fwstate = bfa_ioc_ct_set_cur_ioc_fwstate; +	hwif->ioc_get_fwstate = bfa_ioc_ct_get_cur_ioc_fwstate; +	hwif->ioc_set_alt_fwstate = bfa_ioc_ct_set_alt_ioc_fwstate; +	hwif->ioc_get_alt_fwstate = bfa_ioc_ct_get_alt_ioc_fwstate; +} + +/** + * Called from bfa_ioc_attach() to map asic specific calls. + */ +void +bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) +{ +	bfa_ioc_set_ctx_hwif(ioc, &hwif_ct); + +	hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init; +	hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; +	hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; +	hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; +	ioc->ioc_hwif = &hwif_ct; +} + +/** + * Called from bfa_ioc_attach() to map asic specific calls. + */ +void +bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc) +{ +	bfa_ioc_set_ctx_hwif(ioc, &hwif_ct2); + +	hwif_ct2.ioc_pll_init = bfa_ioc_ct2_pll_init; +	hwif_ct2.ioc_reg_init = bfa_ioc_ct2_reg_init; +	hwif_ct2.ioc_map_port = bfa_ioc_ct2_map_port; +	hwif_ct2.ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat; +	hwif_ct2.ioc_isr_mode_set = NULL; +	ioc->ioc_hwif = &hwif_ct2; +} + +/* + * Workaround for MSI-X resource allocation for catapult-2 with no asic block + */ +#define HOSTFN_MSIX_DEFAULT		64 +#define HOSTFN_MSIX_VT_INDEX_MBOX_ERR	0x30138 +#define HOSTFN_MSIX_VT_OFST_NUMVT	0x3013c +#define __MSIX_VT_NUMVT__MK		0x003ff800 +#define __MSIX_VT_NUMVT__SH		11 +#define __MSIX_VT_NUMVT_(_v)		((_v) << __MSIX_VT_NUMVT__SH) +#define __MSIX_VT_OFST_			0x000007ff +void +bfa_ioc_ct2_poweron(struct bfa_ioc_s *ioc) +{ +	void __iomem *rb = ioc->pcidev.pci_bar_kva; +	u32	r32; + +	r32 = readl(rb + HOSTFN_MSIX_VT_OFST_NUMVT); +	if (r32 & __MSIX_VT_NUMVT__MK) { +		writel(r32 & __MSIX_VT_OFST_, +			rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR); +		return; +	} + +	writel(__MSIX_VT_NUMVT_(HOSTFN_MSIX_DEFAULT - 1) | +		HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc), +		rb + HOSTFN_MSIX_VT_OFST_NUMVT); +	writel(HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc), +		rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR); +} +  bfa_status_t -bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode) +bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode)  {  	u32	pll_sclk, pll_fclk, r32; +	bfa_boolean_t fcmode = (mode == BFI_ASIC_MODE_FC); + +	pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST | +		__APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) | +		__APP_PLL_SCLK_JITLMT0_1(3U) | +		__APP_PLL_SCLK_CNTLMT0_1(1U); +	pll_fclk = __APP_PLL_LCLK_LRESETN | __APP_PLL_LCLK_ENARST | +		__APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) | +		__APP_PLL_LCLK_JITLMT0_1(3U) | +		__APP_PLL_LCLK_CNTLMT0_1(1U); -	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST | -		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) | -		__APP_PLL_312_JITLMT0_1(3U) | -		__APP_PLL_312_CNTLMT0_1(1U); -	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST | -		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) | -		__APP_PLL_425_JITLMT0_1(3U) | -		__APP_PLL_425_CNTLMT0_1(1U);  	if (fcmode) {  		writel(0, (rb + OP_MODE));  		writel(__APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 | @@ -369,20 +616,21 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)  	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));  	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));  	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK)); -	writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET, -			rb + APP_PLL_312_CTL_REG); -	writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET, -			rb + APP_PLL_425_CTL_REG); -	writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE, -			rb + APP_PLL_312_CTL_REG); -	writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE, -			rb + APP_PLL_425_CTL_REG); +	writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET, +			rb + APP_PLL_SCLK_CTL_REG); +	writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET, +			rb + APP_PLL_LCLK_CTL_REG); +	writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET | +		__APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG); +	writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET | +		__APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG);  	readl(rb + HOSTFN0_INT_MSK);  	udelay(2000);  	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));  	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS)); -	writel(pll_sclk | __APP_PLL_312_ENABLE, rb + APP_PLL_312_CTL_REG); -	writel(pll_fclk | __APP_PLL_425_ENABLE, rb + APP_PLL_425_CTL_REG); +	writel(pll_sclk | __APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG); +	writel(pll_fclk | __APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG); +  	if (!fcmode) {  		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));  		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1)); @@ -402,3 +650,348 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)  	writel(0, (rb + MBIST_CTL_REG));  	return BFA_STATUS_OK;  } + +static void +bfa_ioc_ct2_sclk_init(void __iomem *rb) +{ +	u32 r32; + +	/* +	 * put s_clk PLL and PLL FSM in reset +	 */ +	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); +	r32 &= ~(__APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN); +	r32 |= (__APP_PLL_SCLK_ENARST | __APP_PLL_SCLK_BYPASS | +		__APP_PLL_SCLK_LOGIC_SOFT_RESET); +	writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG)); + +	/* +	 * Ignore mode and program for the max clock (which is FC16) +	 * Firmware/NFC will do the PLL init appropiately +	 */ +	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); +	r32 &= ~(__APP_PLL_SCLK_REFCLK_SEL | __APP_PLL_SCLK_CLK_DIV2); +	writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG)); + +	/* +	 * while doing PLL init dont clock gate ethernet subsystem +	 */ +	r32 = readl((rb + CT2_CHIP_MISC_PRG)); +	writel(r32 | __ETH_CLK_ENABLE_PORT0, (rb + CT2_CHIP_MISC_PRG)); + +	r32 = readl((rb + CT2_PCIE_MISC_REG)); +	writel(r32 | __ETH_CLK_ENABLE_PORT1, (rb + CT2_PCIE_MISC_REG)); + +	/* +	 * set sclk value +	 */ +	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); +	r32 &= (__P_SCLK_PLL_LOCK | __APP_PLL_SCLK_REFCLK_SEL | +		__APP_PLL_SCLK_CLK_DIV2); +	writel(r32 | 0x1061731b, (rb + CT2_APP_PLL_SCLK_CTL_REG)); + +	/* +	 * poll for s_clk lock or delay 1ms +	 */ +	udelay(1000); +} + +static void +bfa_ioc_ct2_lclk_init(void __iomem *rb) +{ +	u32 r32; + +	/* +	 * put l_clk PLL and PLL FSM in reset +	 */ +	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); +	r32 &= ~(__APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN); +	r32 |= (__APP_PLL_LCLK_ENARST | __APP_PLL_LCLK_BYPASS | +		__APP_PLL_LCLK_LOGIC_SOFT_RESET); +	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG)); + +	/* +	 * set LPU speed (set for FC16 which will work for other modes) +	 */ +	r32 = readl((rb + CT2_CHIP_MISC_PRG)); +	writel(r32, (rb + CT2_CHIP_MISC_PRG)); + +	/* +	 * set LPU half speed (set for FC16 which will work for other modes) +	 */ +	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); +	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG)); + +	/* +	 * set lclk for mode (set for FC16) +	 */ +	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); +	r32 &= (__P_LCLK_PLL_LOCK | __APP_LPUCLK_HALFSPEED); +	r32 |= 0x20c1731b; +	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG)); + +	/* +	 * poll for s_clk lock or delay 1ms +	 */ +	udelay(1000); +} + +static void +bfa_ioc_ct2_mem_init(void __iomem *rb) +{ +	u32	r32; + +	r32 = readl((rb + PSS_CTL_REG)); +	r32 &= ~__PSS_LMEM_RESET; +	writel(r32, (rb + PSS_CTL_REG)); +	udelay(1000); + +	writel(__EDRAM_BISTR_START, (rb + CT2_MBIST_CTL_REG)); +	udelay(1000); +	writel(0, (rb + CT2_MBIST_CTL_REG)); +} + +void +bfa_ioc_ct2_mac_reset(void __iomem *rb) +{ +	/* put port0, port1 MAC & AHB in reset */ +	writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET), +		rb + CT2_CSI_MAC_CONTROL_REG(0)); +	writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET), +		rb + CT2_CSI_MAC_CONTROL_REG(1)); +} + +static void +bfa_ioc_ct2_enable_flash(void __iomem *rb) +{ +	u32 r32; + +	r32 = readl((rb + PSS_GPIO_OUT_REG)); +	writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG)); +	r32 = readl((rb + PSS_GPIO_OE_REG)); +	writel(r32 | 1, (rb + PSS_GPIO_OE_REG)); +} + +#define CT2_NFC_MAX_DELAY	1000 +#define CT2_NFC_PAUSE_MAX_DELAY 4000 +#define CT2_NFC_VER_VALID	0x147 +#define CT2_NFC_STATE_RUNNING   0x20000001 +#define BFA_IOC_PLL_POLL	1000000 + +static bfa_boolean_t +bfa_ioc_ct2_nfc_halted(void __iomem *rb) +{ +	u32	r32; + +	r32 = readl(rb + CT2_NFC_CSR_SET_REG); +	if (r32 & __NFC_CONTROLLER_HALTED) +		return BFA_TRUE; + +	return BFA_FALSE; +} + +static void +bfa_ioc_ct2_nfc_halt(void __iomem *rb) +{ +	int	i; + +	writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG); +	for (i = 0; i < CT2_NFC_MAX_DELAY; i++) { +		if (bfa_ioc_ct2_nfc_halted(rb)) +			break; +		udelay(1000); +	} +	WARN_ON(!bfa_ioc_ct2_nfc_halted(rb)); +} + +static void +bfa_ioc_ct2_nfc_resume(void __iomem *rb) +{ +	u32	r32; +	int i; + +	writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_CLR_REG); +	for (i = 0; i < CT2_NFC_MAX_DELAY; i++) { +		r32 = readl(rb + CT2_NFC_CSR_SET_REG); +		if (!(r32 & __NFC_CONTROLLER_HALTED)) +			return; +		udelay(1000); +	} +	WARN_ON(1); +} + +static void +bfa_ioc_ct2_clk_reset(void __iomem *rb) +{ +	u32 r32; + +	bfa_ioc_ct2_sclk_init(rb); +	bfa_ioc_ct2_lclk_init(rb); + +	/* +	 * release soft reset on s_clk & l_clk +	 */ +	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG)); +	writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET, +			(rb + CT2_APP_PLL_SCLK_CTL_REG)); + +	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG)); +	writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET, +			(rb + CT2_APP_PLL_LCLK_CTL_REG)); + +} + +static void +bfa_ioc_ct2_nfc_clk_reset(void __iomem *rb) +{ +	u32 r32, i; + +	r32 = readl((rb + PSS_CTL_REG)); +	r32 |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET); +	writel(r32, (rb + PSS_CTL_REG)); + +	writel(__RESET_AND_START_SCLK_LCLK_PLLS, rb + CT2_CSI_FW_CTL_SET_REG); + +	for (i = 0; i < BFA_IOC_PLL_POLL; i++) { +		r32 = readl(rb + CT2_NFC_FLASH_STS_REG); + +		if ((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)) +			break; +	} +	WARN_ON(!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)); + +	for (i = 0; i < BFA_IOC_PLL_POLL; i++) { +		r32 = readl(rb + CT2_NFC_FLASH_STS_REG); + +		if (!(r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)) +			break; +	} +	WARN_ON((r32 & __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS)); + +	r32 = readl(rb + CT2_CSI_FW_CTL_REG); +	WARN_ON((r32 & __RESET_AND_START_SCLK_LCLK_PLLS)); +} + +static void +bfa_ioc_ct2_wait_till_nfc_running(void __iomem *rb) +{ +	u32 r32; +	int i; + +	if (bfa_ioc_ct2_nfc_halted(rb)) +		bfa_ioc_ct2_nfc_resume(rb); +	for (i = 0; i < CT2_NFC_PAUSE_MAX_DELAY; i++) { +		r32 = readl(rb + CT2_NFC_STS_REG); +		if (r32 == CT2_NFC_STATE_RUNNING) +			return; +		udelay(1000); +	} + +	r32 = readl(rb + CT2_NFC_STS_REG); +	WARN_ON(!(r32 == CT2_NFC_STATE_RUNNING)); +} + +bfa_status_t +bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode) +{ +	u32 wgn, r32, nfc_ver; + +	wgn = readl(rb + CT2_WGN_STATUS); + +	if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) { +		/* +		 * If flash is corrupted, enable flash explicitly +		 */ +		bfa_ioc_ct2_clk_reset(rb); +		bfa_ioc_ct2_enable_flash(rb); + +		bfa_ioc_ct2_mac_reset(rb); + +		bfa_ioc_ct2_clk_reset(rb); +		bfa_ioc_ct2_enable_flash(rb); + +	} else { +		nfc_ver = readl(rb + CT2_RSC_GPR15_REG); + +		if ((nfc_ver >= CT2_NFC_VER_VALID) && +		    (wgn == (__A2T_AHB_LOAD | __WGN_READY))) { + +			bfa_ioc_ct2_wait_till_nfc_running(rb); + +			bfa_ioc_ct2_nfc_clk_reset(rb); +		} else { +			bfa_ioc_ct2_nfc_halt(rb); + +			bfa_ioc_ct2_clk_reset(rb); +			bfa_ioc_ct2_mac_reset(rb); +			bfa_ioc_ct2_clk_reset(rb); + +		} +	} +	/* +	* The very first PCIe DMA Read done by LPU fails with a fatal error, +	* when Address Translation Cache (ATC) has been enabled by system BIOS. +	* +	* Workaround: +	* Disable Invalidated Tag Match Enable capability by setting the bit 26 +	* of CHIP_MISC_PRG to 0, by default it is set to 1. +	*/ +	r32 = readl(rb + CT2_CHIP_MISC_PRG); +	writel((r32 & 0xfbffffff), (rb + CT2_CHIP_MISC_PRG)); + +	/* +	 * Mask the interrupts and clear any +	 * pending interrupts left by BIOS/EFI +	 */ + +	writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK)); +	writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK)); + +	/* For first time initialization, no need to clear interrupts */ +	r32 = readl(rb + HOST_SEM5_REG); +	if (r32 & 0x1) { +		r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT)); +		if (r32 == 1) { +			writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT)); +			readl((rb + CT2_LPU0_HOSTFN_CMD_STAT)); +		} +		r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT)); +		if (r32 == 1) { +			writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT)); +			readl((rb + CT2_LPU1_HOSTFN_CMD_STAT)); +		} +	} + +	bfa_ioc_ct2_mem_init(rb); + +	writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG)); +	writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG)); + +	return BFA_STATUS_OK; +} + +static void +bfa_ioc_ct_set_cur_ioc_fwstate(struct bfa_ioc_s *ioc, +		enum bfi_ioc_state fwstate) +{ +	writel(fwstate, ioc->ioc_regs.ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_ct_get_cur_ioc_fwstate(struct bfa_ioc_s *ioc) +{ +	return (enum bfi_ioc_state)readl(ioc->ioc_regs.ioc_fwstate); +} + +static void +bfa_ioc_ct_set_alt_ioc_fwstate(struct bfa_ioc_s *ioc, +		enum bfi_ioc_state fwstate) +{ +	writel(fwstate, ioc->ioc_regs.alt_ioc_fwstate); +} + +static enum bfi_ioc_state +bfa_ioc_ct_get_alt_ioc_fwstate(struct bfa_ioc_s *ioc) +{ +	return (enum bfi_ioc_state) readl(ioc->ioc_regs.alt_ioc_fwstate); +} diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h index 15407ab39e7..a14c784ff3f 100644 --- a/drivers/scsi/bfa/bfa_modules.h +++ b/drivers/scsi/bfa/bfa_modules.h @@ -29,14 +29,23 @@  #include "bfa_port.h"  struct bfa_modules_s { +	struct bfa_fcdiag_s	fcdiag;		/* fcdiag module */  	struct bfa_fcport_s	fcport;		/*  fc port module	      */  	struct bfa_fcxp_mod_s	fcxp_mod;	/*  fcxp module	      */  	struct bfa_lps_mod_s	lps_mod;	/*  fcxp module	      */  	struct bfa_uf_mod_s	uf_mod;		/*  unsolicited frame module */  	struct bfa_rport_mod_s	rport_mod;	/*  remote port module	      */ -	struct bfa_fcpim_mod_s	fcpim_mod;	/*  FCP initiator module     */ +	struct bfa_fcp_mod_s	fcp_mod;	/*  FCP initiator module     */  	struct bfa_sgpg_mod_s	sgpg_mod;	/*  SG page module	      */  	struct bfa_port_s	port;		/*  Physical port module     */ +	struct bfa_ablk_s	ablk;		/*  ASIC block config module */ +	struct bfa_cee_s	cee;		/*  CEE Module	*/ +	struct bfa_sfp_s	sfp;		/*  SFP module	*/ +	struct bfa_flash_s	flash;		/*  flash module */ +	struct bfa_diag_s	diag_mod;	/*  diagnostics module	*/ +	struct bfa_phy_s	phy;		/*  phy module		*/ +	struct bfa_dconf_mod_s	dconf_mod;	/*  DCONF common module	*/ +	struct bfa_fru_s	fru;		/*  fru module		*/  };  /* @@ -51,17 +60,16 @@ enum {  	BFA_TRC_HAL_IOCFC_CB	= 5,  }; -  /*   * Macro to define a new BFA module   */  #define BFA_MODULE(__mod)						\  	static void bfa_ ## __mod ## _meminfo(				\ -			struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,	\ -			u32 *dm_len);      \ +			struct bfa_iocfc_cfg_s *cfg,			\ +			struct bfa_meminfo_s *meminfo,			\ +			struct bfa_s *bfa);				\  	static void bfa_ ## __mod ## _attach(struct bfa_s *bfa,		\  			void *bfad, struct bfa_iocfc_cfg_s *cfg,	\ -			struct bfa_meminfo_s *meminfo,			\  			struct bfa_pcidev_s *pcidev);      \  	static void bfa_ ## __mod ## _detach(struct bfa_s *bfa);      \  	static void bfa_ ## __mod ## _start(struct bfa_s *bfa);      \ @@ -87,11 +95,11 @@ enum {   * can leave entry points as NULL)   */  struct bfa_module_s { -	void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -			u32 *dm_len); +	void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, +			 struct bfa_meminfo_s *meminfo, +			 struct bfa_s *bfa);  	void (*attach) (struct bfa_s *bfa, void *bfad,  			struct bfa_iocfc_cfg_s *cfg, -			struct bfa_meminfo_s *meminfo,  			struct bfa_pcidev_s *pcidev);  	void (*detach) (struct bfa_s *bfa);  	void (*start) (struct bfa_s *bfa); @@ -99,7 +107,6 @@ struct bfa_module_s {  	void (*iocdisable) (struct bfa_s *bfa);  }; -extern struct bfa_module_s *hal_mods[];  struct bfa_s {  	void			*bfad;		/*  BFA driver instance    */ @@ -110,21 +117,23 @@ struct bfa_s {  	struct bfa_timer_mod_s	timer_mod;	/*  timer module	    */  	struct bfa_modules_s	modules;	/*  BFA modules	    */  	struct list_head	comp_q;		/*  pending completions     */ -	bfa_boolean_t		rme_process;	/*  RME processing enabled  */ +	bfa_boolean_t		queue_process;	/*  queue processing enabled */  	struct list_head	reqq_waitq[BFI_IOC_MAX_CQS];  	bfa_boolean_t		fcs;		/*  FCS is attached to BFA */  	struct bfa_msix_s	msix; +	int			bfa_aen_seq; +	bfa_boolean_t		intr_enabled;	/*  Status of interrupts */  }; -extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX]; -extern bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[];  extern bfa_boolean_t bfa_auto_recover; +extern struct bfa_module_s hal_mod_fcdiag;  extern struct bfa_module_s hal_mod_sgpg;  extern struct bfa_module_s hal_mod_fcport;  extern struct bfa_module_s hal_mod_fcxp;  extern struct bfa_module_s hal_mod_lps;  extern struct bfa_module_s hal_mod_uf;  extern struct bfa_module_s hal_mod_rport; -extern struct bfa_module_s hal_mod_fcpim; +extern struct bfa_module_s hal_mod_fcp; +extern struct bfa_module_s hal_mod_dconf;  #endif /* __BFA_MODULES_H__ */ diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h deleted file mode 100644 index 65df62ef437..00000000000 --- a/drivers/scsi/bfa/bfa_os_inc.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. - * All rights reserved - * www.brocade.com - * - * Linux driver for Brocade Fibre Channel Host Bus Adapter. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License (GPL) Version 2 as - * published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - */ - -#ifndef __BFA_OS_INC_H__ -#define __BFA_OS_INC_H__ - -#include <linux/types.h> -#include <linux/version.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/idr.h> -#include <linux/interrupt.h> -#include <linux/cdev.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/vmalloc.h> -#include <linux/workqueue.h> -#include <linux/bitops.h> -#include <scsi/scsi.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_tcq.h> -#include <scsi/scsi_transport_fc.h> -#include <scsi/scsi_transport.h> - -#ifdef __BIG_ENDIAN -#define __BIGENDIAN -#endif - -static inline u64 bfa_os_get_log_time(void) -{ -	u64 system_time = 0; -	struct timeval tv; -	do_gettimeofday(&tv); - -	/* We are interested in seconds only. */ -	system_time = tv.tv_sec; -	return system_time; -} - -#define bfa_io_lat_clock_res_div HZ -#define bfa_io_lat_clock_res_mul 1000 - -#define BFA_LOG(level, bfad, mask, fmt, arg...)				\ -do {									\ -	if (((mask) == 4) || (level[1] <= '4'))				\ -		dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg);	\ -} while (0) - -#define bfa_swap_3b(_x)				\ -	((((_x) & 0xff) << 16) |		\ -	((_x) & 0x00ff00) |			\ -	(((_x) & 0xff0000) >> 16)) - -#define bfa_os_swap_sgaddr(_x)  ((u64)(                                 \ -	(((u64)(_x) & (u64)0x00000000000000ffull) << 32)        |       \ -	(((u64)(_x) & (u64)0x000000000000ff00ull) << 32)        |       \ -	(((u64)(_x) & (u64)0x0000000000ff0000ull) << 32)        |       \ -	(((u64)(_x) & (u64)0x00000000ff000000ull) << 32)        |       \ -	(((u64)(_x) & (u64)0x000000ff00000000ull) >> 32)        |       \ -	(((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32)        |       \ -	(((u64)(_x) & (u64)0x00ff000000000000ull) >> 32)        |       \ -	(((u64)(_x) & (u64)0xff00000000000000ull) >> 32))) - -#ifndef __BIGENDIAN -#define bfa_os_hton3b(_x)  bfa_swap_3b(_x) -#define bfa_os_sgaddr(_x)  (_x) -#else -#define bfa_os_hton3b(_x)  (_x) -#define bfa_os_sgaddr(_x)  bfa_os_swap_sgaddr(_x) -#endif - -#define bfa_os_ntoh3b(_x)  bfa_os_hton3b(_x) -#define bfa_os_u32(__pa64) ((__pa64) >> 32) - -#define BFA_TRC_TS(_trcm)				\ -	({						\ -		struct timeval tv;			\ -							\ -		do_gettimeofday(&tv);			\ -		(tv.tv_sec*1000000+tv.tv_usec);		\ -	 }) - -#define boolean_t int - -/* - * For current time stamp, OS API will fill-in - */ -struct bfa_timeval_s { -	u32	tv_sec;		/*  seconds        */ -	u32	tv_usec;	/*  microseconds   */ -}; - -static inline void -bfa_os_gettimeofday(struct bfa_timeval_s *tv) -{ -	struct timeval  tmp_tv; - -	do_gettimeofday(&tmp_tv); -	tv->tv_sec = (u32) tmp_tv.tv_sec; -	tv->tv_usec = (u32) tmp_tv.tv_usec; -} - -static inline void -wwn2str(char *wwn_str, u64 wwn) -{ -	union { -		u64 wwn; -		u8 byte[8]; -	} w; - -	w.wwn = wwn; -	sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0], -		w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5], -		w.byte[6], w.byte[7]); -} - -static inline void -fcid2str(char *fcid_str, u32 fcid) -{ -	union { -		u32 fcid; -		u8 byte[4]; -	} f; - -	f.fcid = fcid; -	sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]); -} - -#endif /* __BFA_OS_INC_H__ */ diff --git a/drivers/scsi/bfa/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h index 501f0ed35cf..1c9baa68339 100644 --- a/drivers/scsi/bfa/bfa_plog.h +++ b/drivers/scsi/bfa/bfa_plog.h @@ -151,9 +151,5 @@ void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,  void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,  			enum bfa_plog_eid event, u16 misc,  			struct fchs_s *fchdr, u32 pld_w0); -void bfa_plog_clear(struct bfa_plog_s *plog); -void bfa_plog_enable(struct bfa_plog_s *plog); -void bfa_plog_disable(struct bfa_plog_s *plog); -bfa_boolean_t	bfa_plog_get_setting(struct bfa_plog_s *plog);  #endif /* __BFA_PORTLOG_H__ */ diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index fff96226a38..8ea7697deb9 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -15,6 +15,7 @@   * General Public License for more details.   */ +#include "bfad_drv.h"  #include "bfa_defs_svc.h"  #include "bfa_port.h"  #include "bfi.h" @@ -23,20 +24,18 @@  BFA_TRC_FILE(CNA, PORT); -#define bfa_ioc_portid(__ioc) ((__ioc)->port_id) -  static void  bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)  {  	u32    *dip = (u32 *) stats; -	u32    t0, t1; +	__be32    t0, t1;  	int	    i;  	for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32);  		i += 2) {  		t0 = dip[i];  		t1 = dip[i + 1]; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  		dip[i] = be32_to_cpu(t0);  		dip[i + 1] = be32_to_cpu(t1);  #else @@ -96,13 +95,13 @@ bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status)  	port->stats_busy = BFA_FALSE;  	if (status == BFA_STATUS_OK) { -		struct bfa_timeval_s tv; +		struct timeval tv;  		memcpy(port->stats, port->stats_dma.kva,  		       sizeof(union bfa_port_stats_u));  		bfa_port_stats_swap(port, port->stats); -		bfa_os_gettimeofday(&tv); +		do_gettimeofday(&tv);  		port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time;  	} @@ -124,7 +123,7 @@ bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status)  static void  bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)  { -	struct bfa_timeval_s tv; +	struct timeval tv;  	port->stats_status = status;  	port->stats_busy   = BFA_FALSE; @@ -132,7 +131,7 @@ bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)  	/*  	* re-initialize time stamp for stats reset  	*/ -	bfa_os_gettimeofday(&tv); +	do_gettimeofday(&tv);  	port->stats_reset_time = tv.tv_sec;  	if (port->stats_cbfn) { @@ -185,7 +184,7 @@ bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)  		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  	}  } @@ -235,6 +234,12 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,  {  	struct bfi_port_generic_req_s *m; +	/* If port is PBC disabled, return error */ +	if (port->pbc_disabled) { +		bfa_trc(port, BFA_STATUS_PBC); +		return BFA_STATUS_PBC; +	} +  	if (bfa_ioc_is_disabled(port->ioc)) {  		bfa_trc(port, BFA_STATUS_IOC_DISABLED);  		return BFA_STATUS_IOC_DISABLED; @@ -245,6 +250,12 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,  		return BFA_STATUS_IOC_FAILURE;  	} +	/* if port is d-port enabled, return error */ +	if (port->dport_enabled) { +		bfa_trc(port, BFA_STATUS_DPORT_ERR); +		return BFA_STATUS_DPORT_ERR; +	} +  	if (port->endis_pending) {  		bfa_trc(port, BFA_STATUS_DEVBUSY);  		return BFA_STATUS_DEVBUSY; @@ -279,6 +290,12 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,  {  	struct bfi_port_generic_req_s *m; +	/* If port is PBC disabled, return error */ +	if (port->pbc_disabled) { +		bfa_trc(port, BFA_STATUS_PBC); +		return BFA_STATUS_PBC; +	} +  	if (bfa_ioc_is_disabled(port->ioc)) {  		bfa_trc(port, BFA_STATUS_IOC_DISABLED);  		return BFA_STATUS_IOC_DISABLED; @@ -289,6 +306,12 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,  		return BFA_STATUS_IOC_FAILURE;  	} +	/* if port is d-port enabled, return error */ +	if (port->dport_enabled) { +		bfa_trc(port, BFA_STATUS_DPORT_ERR); +		return BFA_STATUS_DPORT_ERR; +	} +  	if (port->endis_pending) {  		bfa_trc(port, BFA_STATUS_DEVBUSY);  		return BFA_STATUS_DEVBUSY; @@ -386,32 +409,47 @@ bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,  }  /* - * bfa_port_hbfail() + * bfa_port_notify()   * + * Port module IOC event handler   *   * @param[in] Pointer to the Port module data structure. + * @param[in] IOC event structure   *   * @return void   */  void -bfa_port_hbfail(void *arg) +bfa_port_notify(void *arg, enum bfa_ioc_event_e event)  {  	struct bfa_port_s *port = (struct bfa_port_s *) arg; -	/* Fail any pending get_stats/clear_stats requests */ -	if (port->stats_busy) { -		if (port->stats_cbfn) -			port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED); -		port->stats_cbfn = NULL; -		port->stats_busy = BFA_FALSE; -	} - -	/* Clear any enable/disable is pending */ -	if (port->endis_pending) { -		if (port->endis_cbfn) -			port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED); -		port->endis_cbfn = NULL; -		port->endis_pending = BFA_FALSE; +	switch (event) { +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		/* Fail any pending get_stats/clear_stats requests */ +		if (port->stats_busy) { +			if (port->stats_cbfn) +				port->stats_cbfn(port->stats_cbarg, +						BFA_STATUS_FAILED); +			port->stats_cbfn = NULL; +			port->stats_busy = BFA_FALSE; +		} + +		/* Clear any enable/disable is pending */ +		if (port->endis_pending) { +			if (port->endis_cbfn) +				port->endis_cbfn(port->endis_cbarg, +						BFA_STATUS_FAILED); +			port->endis_cbfn = NULL; +			port->endis_pending = BFA_FALSE; +		} + +		/* clear D-port mode */ +		if (port->dport_enabled) +			bfa_port_set_dportenabled(port, BFA_FALSE); +		break; +	default: +		break;  	}  } @@ -432,9 +470,9 @@ void  bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,  		 void *dev, struct bfa_trc_mod_s *trcmod)  { -	struct bfa_timeval_s tv; +	struct timeval tv; -	bfa_assert(port); +	WARN_ON(!port);  	port->dev    = dev;  	port->ioc    = ioc; @@ -444,30 +482,399 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,  	port->endis_pending = BFA_FALSE;  	port->stats_cbfn = NULL;  	port->endis_cbfn = NULL; +	port->pbc_disabled = BFA_FALSE; +	port->dport_enabled = BFA_FALSE;  	bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port); -	bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port); -	bfa_ioc_hbfail_register(port->ioc, &port->hbfail); +	bfa_q_qe_init(&port->ioc_notify); +	bfa_ioc_notify_init(&port->ioc_notify, bfa_port_notify, port); +	list_add_tail(&port->ioc_notify.qe, &port->ioc->notify_q);  	/*  	 * initialize time stamp for stats reset  	 */ -	bfa_os_gettimeofday(&tv); +	do_gettimeofday(&tv);  	port->stats_reset_time = tv.tv_sec;  	bfa_trc(port, 0);  }  /* - * bfa_port_detach() + * bfa_port_set_dportenabled();   * + * Port module- set pbc disabled flag   *   * @param[in] port - Pointer to the Port module data structure   *   * @return void   */  void -bfa_port_detach(struct bfa_port_s *port) +bfa_port_set_dportenabled(struct bfa_port_s *port, bfa_boolean_t enabled)  { -	bfa_trc(port, 0); +	port->dport_enabled = enabled; +} + +/* + *	CEE module specific definitions + */ + +/* + * bfa_cee_get_attr_isr() + * + * @brief CEE ISR for get-attributes responses from f/w + * + * @param[in] cee - Pointer to the CEE module + *		    status - Return status from the f/w + * + * @return void + */ +static void +bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status) +{ +	struct bfa_cee_lldp_cfg_s *lldp_cfg = &cee->attr->lldp_remote; + +	cee->get_attr_status = status; +	bfa_trc(cee, 0); +	if (status == BFA_STATUS_OK) { +		bfa_trc(cee, 0); +		memcpy(cee->attr, cee->attr_dma.kva, +			sizeof(struct bfa_cee_attr_s)); +		lldp_cfg->time_to_live = be16_to_cpu(lldp_cfg->time_to_live); +		lldp_cfg->enabled_system_cap = +				be16_to_cpu(lldp_cfg->enabled_system_cap); +	} +	cee->get_attr_pending = BFA_FALSE; +	if (cee->cbfn.get_attr_cbfn) { +		bfa_trc(cee, 0); +		cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status); +	} +} + +/* + * bfa_cee_get_stats_isr() + * + * @brief CEE ISR for get-stats responses from f/w + * + * @param[in] cee - Pointer to the CEE module + *	      status - Return status from the f/w + * + * @return void + */ +static void +bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) +{ +	u32 *buffer; +	int i; + +	cee->get_stats_status = status; +	bfa_trc(cee, 0); +	if (status == BFA_STATUS_OK) { +		bfa_trc(cee, 0); +		memcpy(cee->stats, cee->stats_dma.kva, +			sizeof(struct bfa_cee_stats_s)); +		/* swap the cee stats */ +		buffer = (u32 *)cee->stats; +		for (i = 0; i < (sizeof(struct bfa_cee_stats_s) / +				 sizeof(u32)); i++) +			buffer[i] = cpu_to_be32(buffer[i]); +	} +	cee->get_stats_pending = BFA_FALSE; +	bfa_trc(cee, 0); +	if (cee->cbfn.get_stats_cbfn) { +		bfa_trc(cee, 0); +		cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status); +	} +} + +/* + * bfa_cee_reset_stats_isr() + * + * @brief CEE ISR for reset-stats responses from f/w + * + * @param[in] cee - Pointer to the CEE module + *            status - Return status from the f/w + * + * @return void + */ +static void +bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) +{ +	cee->reset_stats_status = status; +	cee->reset_stats_pending = BFA_FALSE; +	if (cee->cbfn.reset_stats_cbfn) +		cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); +} + +/* + * bfa_cee_meminfo() + * + * @brief Returns the size of the DMA memory needed by CEE module + * + * @param[in] void + * + * @return Size of DMA region + */ +u32 +bfa_cee_meminfo(void) +{ +	return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ) + +		BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ); +} + +/* + * bfa_cee_mem_claim() + * + * @brief Initialized CEE DMA Memory + * + * @param[in] cee CEE module pointer + *            dma_kva Kernel Virtual Address of CEE DMA Memory + *            dma_pa  Physical Address of CEE DMA Memory + * + * @return void + */ +void +bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa) +{ +	cee->attr_dma.kva = dma_kva; +	cee->attr_dma.pa = dma_pa; +	cee->stats_dma.kva = dma_kva + BFA_ROUNDUP( +			     sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ); +	cee->stats_dma.pa = dma_pa + BFA_ROUNDUP( +			     sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ); +	cee->attr = (struct bfa_cee_attr_s *) dma_kva; +	cee->stats = (struct bfa_cee_stats_s *) (dma_kva + BFA_ROUNDUP( +			sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ)); +} + +/* + * bfa_cee_get_attr() + * + * @brief + *   Send the request to the f/w to fetch CEE attributes. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return Status + */ + +bfa_status_t +bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr, +		 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_cee_get_req_s *cmd; + +	WARN_ON((cee == NULL) || (cee->ioc == NULL)); +	bfa_trc(cee, 0); +	if (!bfa_ioc_is_operational(cee->ioc)) { +		bfa_trc(cee, 0); +		return BFA_STATUS_IOC_FAILURE; +	} +	if (cee->get_attr_pending == BFA_TRUE) { +		bfa_trc(cee, 0); +		return  BFA_STATUS_DEVBUSY; +	} +	cee->get_attr_pending = BFA_TRUE; +	cmd = (struct bfi_cee_get_req_s *) cee->get_cfg_mb.msg; +	cee->attr = attr; +	cee->cbfn.get_attr_cbfn = cbfn; +	cee->cbfn.get_attr_cbarg = cbarg; +	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, +		bfa_ioc_portid(cee->ioc)); +	bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); +	bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb); + +	return BFA_STATUS_OK; +} + +/* + * bfa_cee_get_stats() + * + * @brief + *   Send the request to the f/w to fetch CEE statistics. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return Status + */ + +bfa_status_t +bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats, +		  bfa_cee_get_stats_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_cee_get_req_s *cmd; + +	WARN_ON((cee == NULL) || (cee->ioc == NULL)); + +	if (!bfa_ioc_is_operational(cee->ioc)) { +		bfa_trc(cee, 0); +		return BFA_STATUS_IOC_FAILURE; +	} +	if (cee->get_stats_pending == BFA_TRUE) { +		bfa_trc(cee, 0); +		return  BFA_STATUS_DEVBUSY; +	} +	cee->get_stats_pending = BFA_TRUE; +	cmd = (struct bfi_cee_get_req_s *) cee->get_stats_mb.msg; +	cee->stats = stats; +	cee->cbfn.get_stats_cbfn = cbfn; +	cee->cbfn.get_stats_cbarg = cbarg; +	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, +		bfa_ioc_portid(cee->ioc)); +	bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa); +	bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb); + +	return BFA_STATUS_OK; +} + +/* + * bfa_cee_reset_stats() + * + * @brief Clears CEE Stats in the f/w. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return Status + */ + +bfa_status_t +bfa_cee_reset_stats(struct bfa_cee_s *cee, +		    bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg) +{ +	struct bfi_cee_reset_stats_s *cmd; + +	WARN_ON((cee == NULL) || (cee->ioc == NULL)); +	if (!bfa_ioc_is_operational(cee->ioc)) { +		bfa_trc(cee, 0); +		return BFA_STATUS_IOC_FAILURE; +	} +	if (cee->reset_stats_pending == BFA_TRUE) { +		bfa_trc(cee, 0); +		return  BFA_STATUS_DEVBUSY; +	} +	cee->reset_stats_pending = BFA_TRUE; +	cmd = (struct bfi_cee_reset_stats_s *) cee->reset_stats_mb.msg; +	cee->cbfn.reset_stats_cbfn = cbfn; +	cee->cbfn.reset_stats_cbarg = cbarg; +	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, +		bfa_ioc_portid(cee->ioc)); +	bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb); + +	return BFA_STATUS_OK; +} + +/* + * bfa_cee_isrs() + * + * @brief Handles Mail-box interrupts for CEE module. + * + * @param[in] Pointer to the CEE module data structure. + * + * @return void + */ + +void +bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m) +{ +	union bfi_cee_i2h_msg_u *msg; +	struct bfi_cee_get_rsp_s *get_rsp; +	struct bfa_cee_s *cee = (struct bfa_cee_s *) cbarg; +	msg = (union bfi_cee_i2h_msg_u *) m; +	get_rsp = (struct bfi_cee_get_rsp_s *) m; +	bfa_trc(cee, msg->mh.msg_id); +	switch (msg->mh.msg_id) { +	case BFI_CEE_I2H_GET_CFG_RSP: +		bfa_trc(cee, get_rsp->cmd_status); +		bfa_cee_get_attr_isr(cee, get_rsp->cmd_status); +		break; +	case BFI_CEE_I2H_GET_STATS_RSP: +		bfa_cee_get_stats_isr(cee, get_rsp->cmd_status); +		break; +	case BFI_CEE_I2H_RESET_STATS_RSP: +		bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status); +		break; +	default: +		WARN_ON(1); +	} +} + +/* + * bfa_cee_notify() + * + * @brief CEE module IOC event handler. + * + * @param[in] Pointer to the CEE module data structure. + * @param[in] IOC event type + * + * @return void + */ + +void +bfa_cee_notify(void *arg, enum bfa_ioc_event_e event) +{ +	struct bfa_cee_s *cee = (struct bfa_cee_s *) arg; + +	bfa_trc(cee, event); + +	switch (event) { +	case BFA_IOC_E_DISABLED: +	case BFA_IOC_E_FAILED: +		if (cee->get_attr_pending == BFA_TRUE) { +			cee->get_attr_status = BFA_STATUS_FAILED; +			cee->get_attr_pending  = BFA_FALSE; +			if (cee->cbfn.get_attr_cbfn) { +				cee->cbfn.get_attr_cbfn( +					cee->cbfn.get_attr_cbarg, +					BFA_STATUS_FAILED); +			} +		} +		if (cee->get_stats_pending == BFA_TRUE) { +			cee->get_stats_status = BFA_STATUS_FAILED; +			cee->get_stats_pending  = BFA_FALSE; +			if (cee->cbfn.get_stats_cbfn) { +				cee->cbfn.get_stats_cbfn( +				cee->cbfn.get_stats_cbarg, +				BFA_STATUS_FAILED); +			} +		} +		if (cee->reset_stats_pending == BFA_TRUE) { +			cee->reset_stats_status = BFA_STATUS_FAILED; +			cee->reset_stats_pending  = BFA_FALSE; +			if (cee->cbfn.reset_stats_cbfn) { +				cee->cbfn.reset_stats_cbfn( +				cee->cbfn.reset_stats_cbarg, +				BFA_STATUS_FAILED); +			} +		} +		break; + +	default: +		break; +	} +} + +/* + * bfa_cee_attach() + * + * @brief CEE module-attach API + * + * @param[in] cee - Pointer to the CEE module data structure + *            ioc - Pointer to the ioc module data structure + *            dev - Pointer to the device driver module data structure + *                  The device driver specific mbox ISR functions have + *                  this pointer as one of the parameters. + * + * @return void + */ +void +bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, +		void *dev) +{ +	WARN_ON(cee == NULL); +	cee->dev = dev; +	cee->ioc = ioc; + +	bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); +	bfa_q_qe_init(&cee->ioc_notify); +	bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee); +	list_add_tail(&cee->ioc_notify.qe, &cee->ioc->notify_q);  } diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h index dbce9dfd056..2fcab6bc628 100644 --- a/drivers/scsi/bfa/bfa_port.h +++ b/drivers/scsi/bfa/bfa_port.h @@ -43,13 +43,17 @@ struct bfa_port_s {  	bfa_port_endis_cbfn_t		endis_cbfn;  	void				*endis_cbarg;  	bfa_status_t			endis_status; -	struct bfa_ioc_hbfail_notify_s	hbfail; +	struct bfa_ioc_notify_s		ioc_notify; +	bfa_boolean_t			pbc_disabled; +	bfa_boolean_t			dport_enabled; +	struct bfa_mem_dma_s		port_dma;  }; +#define BFA_MEM_PORT_DMA(__bfa)		(&((__bfa)->modules.port.port_dma)) +  void	     bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,  				void *dev, struct bfa_trc_mod_s *trcmod); -void	     bfa_port_detach(struct bfa_port_s *port); -void	     bfa_port_hbfail(void *arg); +void	bfa_port_notify(void *arg, enum bfa_ioc_event_e event);  bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,  				 union bfa_port_stats_u *stats, @@ -63,4 +67,60 @@ bfa_status_t bfa_port_disable(struct bfa_port_s *port,  u32     bfa_port_meminfo(void);  void	     bfa_port_mem_claim(struct bfa_port_s *port,  				 u8 *dma_kva, u64 dma_pa); +void	bfa_port_set_dportenabled(struct bfa_port_s *port, +				  bfa_boolean_t enabled); + +/* + * CEE declaration + */ +typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status); +typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status); +typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status); + +struct bfa_cee_cbfn_s { +	bfa_cee_get_attr_cbfn_t		get_attr_cbfn; +	void				*get_attr_cbarg; +	bfa_cee_get_stats_cbfn_t	get_stats_cbfn; +	void				*get_stats_cbarg; +	bfa_cee_reset_stats_cbfn_t	reset_stats_cbfn; +	void				*reset_stats_cbarg; +}; + +struct bfa_cee_s { +	void *dev; +	bfa_boolean_t		get_attr_pending; +	bfa_boolean_t		get_stats_pending; +	bfa_boolean_t		reset_stats_pending; +	bfa_status_t		get_attr_status; +	bfa_status_t		get_stats_status; +	bfa_status_t		reset_stats_status; +	struct bfa_cee_cbfn_s	cbfn; +	struct bfa_ioc_notify_s	ioc_notify; +	struct bfa_trc_mod_s	*trcmod; +	struct bfa_cee_attr_s	*attr; +	struct bfa_cee_stats_s	*stats; +	struct bfa_dma_s	attr_dma; +	struct bfa_dma_s	stats_dma; +	struct bfa_ioc_s	*ioc; +	struct bfa_mbox_cmd_s	get_cfg_mb; +	struct bfa_mbox_cmd_s	get_stats_mb; +	struct bfa_mbox_cmd_s	reset_stats_mb; +	struct bfa_mem_dma_s	cee_dma; +}; + +#define BFA_MEM_CEE_DMA(__bfa)	(&((__bfa)->modules.cee.cee_dma)) + +u32	bfa_cee_meminfo(void); +void	bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa); +void	bfa_cee_attach(struct bfa_cee_s *cee, +			struct bfa_ioc_s *ioc, void *dev); +bfa_status_t	bfa_cee_get_attr(struct bfa_cee_s *cee, +				struct bfa_cee_attr_s *attr, +				bfa_cee_get_attr_cbfn_t cbfn, void *cbarg); +bfa_status_t	bfa_cee_get_stats(struct bfa_cee_s *cee, +				struct bfa_cee_stats_s *stats, +				bfa_cee_get_stats_cbfn_t cbfn, void *cbarg); +bfa_status_t	bfa_cee_reset_stats(struct bfa_cee_s *cee, +				bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg); +  #endif	/* __BFA_PORT_H__ */ diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index c768143f480..625225f3108 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -15,13 +15,14 @@   * General Public License for more details.   */ -#include "bfa_os_inc.h" +#include "bfad_drv.h" +#include "bfad_im.h"  #include "bfa_plog.h"  #include "bfa_cs.h"  #include "bfa_modules.h" -#include "bfad_drv.h"  BFA_TRC_FILE(HAL, FCXP); +BFA_MODULE(fcdiag);  BFA_MODULE(fcxp);  BFA_MODULE(sgpg);  BFA_MODULE(lps); @@ -41,19 +42,6 @@ BFA_MODULE(uf);  #define BFA_LPS_MAX_VPORTS_SUPP_CB  255  #define BFA_LPS_MAX_VPORTS_SUPP_CT  190 -/* - *  lps_pvt BFA LPS private functions - */ - -enum bfa_lps_event { -	BFA_LPS_SM_LOGIN	= 1,	/* login request from user	*/ -	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user	*/ -	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout	*/ -	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue	*/ -	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user		*/ -	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline		*/ -	BFA_LPS_SM_RX_CVL	= 7,	/* Rx clear virtual link	*/ -};  /*   * FC PORT related definitions @@ -66,7 +54,6 @@ enum bfa_lps_event {  	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \  	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE)) -  /*   * BFA port state machine events   */ @@ -80,6 +67,11 @@ enum bfa_fcport_sm_event {  	BFA_FCPORT_SM_LINKDOWN	= 7,	/*  firmware linkup down	*/  	BFA_FCPORT_SM_QRESUME	= 8,	/*  CQ space available	*/  	BFA_FCPORT_SM_HWFAIL	= 9,	/*  IOC h/w failure		*/ +	BFA_FCPORT_SM_DPORTENABLE = 10, /*  enable dport      */ +	BFA_FCPORT_SM_DPORTDISABLE = 11,/*  disable dport     */ +	BFA_FCPORT_SM_FAA_MISCONFIG = 12,	/* FAA misconfiguratin */ +	BFA_FCPORT_SM_DDPORTENABLE  = 13,	/* enable ddport	*/ +	BFA_FCPORT_SM_DDPORTDISABLE = 14,	/* disable ddport	*/  };  /* @@ -113,19 +105,6 @@ enum bfa_fcport_ln_sm_event {  		}							\  } while (0) - -enum bfa_rport_event { -	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event		*/ -	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport	*/ -	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online		*/ -	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline		*/ -	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response		*/ -	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure		*/ -	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware	*/ -	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed		*/ -	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue	*/ -}; -  /*   * forward declarations FCXP related functions   */ @@ -141,11 +120,10 @@ static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,  /*   * forward declarations for LPS functions   */ -static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, -				u32 *dm_len); +static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, +		struct bfa_meminfo_s *minfo, struct bfa_s *bfa);  static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,  				struct bfa_iocfc_cfg_s *cfg, -				struct bfa_meminfo_s *meminfo,  				struct bfa_pcidev_s *pcidev);  static void bfa_lps_detach(struct bfa_s *bfa);  static void bfa_lps_start(struct bfa_s *bfa); @@ -153,12 +131,14 @@ static void bfa_lps_stop(struct bfa_s *bfa);  static void bfa_lps_iocdisable(struct bfa_s *bfa);  static void bfa_lps_login_rsp(struct bfa_s *bfa,  				struct bfi_lps_login_rsp_s *rsp); +static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);  static void bfa_lps_logout_rsp(struct bfa_s *bfa,  				struct bfi_lps_logout_rsp_s *rsp);  static void bfa_lps_reqq_resume(void *lps_arg);  static void bfa_lps_free(struct bfa_lps_s *lps);  static void bfa_lps_send_login(struct bfa_lps_s *lps);  static void bfa_lps_send_logout(struct bfa_lps_s *lps); +static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);  static void bfa_lps_login_comp(struct bfa_lps_s *lps);  static void bfa_lps_logout_comp(struct bfa_lps_s *lps);  static void bfa_lps_cvl_event(struct bfa_lps_s *lps); @@ -171,6 +151,8 @@ static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);  static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event  					event);  static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event); +static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, +					enum bfa_lps_event event);  static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);  static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event  					event); @@ -220,6 +202,12 @@ static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,  					enum bfa_fcport_sm_event event);  static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,  					enum bfa_fcport_sm_event event); +static void	bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, +					enum bfa_fcport_sm_event event); +static void     bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport, +					enum bfa_fcport_sm_event event); +static void	bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport, +					enum bfa_fcport_sm_event event);  static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,  					enum bfa_fcport_ln_sm_event event); @@ -249,6 +237,9 @@ static struct bfa_sm_table_s hal_port_sm_table[] = {  	{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},  	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},  	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN}, +	{BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT}, +	{BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT}, +	{BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},  }; @@ -312,6 +303,18 @@ plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)  	return 0;  } +static u64 +bfa_get_log_time(void) +{ +	u64 system_time = 0; +	struct timeval tv; +	do_gettimeofday(&tv); + +	/* We are interested in seconds only. */ +	system_time = tv.tv_sec; +	return system_time; +} +  static void  bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)  { @@ -322,7 +325,7 @@ bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)  		return;  	if (plkd_validate_logrec(pl_rec)) { -		bfa_assert(0); +		WARN_ON(1);  		return;  	} @@ -332,7 +335,7 @@ bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)  	memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s)); -	pl_recp->tv = bfa_os_get_log_time(); +	pl_recp->tv = bfa_get_log_time();  	BFA_PL_LOG_REC_INCR(plog->tail);  	if (plog->head == plog->tail) @@ -437,80 +440,25 @@ bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,  	}  } -void -bfa_plog_clear(struct bfa_plog_s *plog) -{ -	plog->head = plog->tail = 0; -} - -void -bfa_plog_enable(struct bfa_plog_s *plog) -{ -	plog->plog_enabled = 1; -} - -void -bfa_plog_disable(struct bfa_plog_s *plog) -{ -	plog->plog_enabled = 0; -} - -bfa_boolean_t -bfa_plog_get_setting(struct bfa_plog_s *plog) -{ -	return (bfa_boolean_t)plog->plog_enabled; -}  /*   *  fcxp_pvt BFA FCXP private functions   */  static void -claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi) -{ -	u8	       *dm_kva = NULL; -	u64	dm_pa; -	u32	buf_pool_sz; - -	dm_kva = bfa_meminfo_dma_virt(mi); -	dm_pa = bfa_meminfo_dma_phys(mi); - -	buf_pool_sz = mod->req_pld_sz * mod->num_fcxps; - -	/* -	 * Initialize the fcxp req payload list -	 */ -	mod->req_pld_list_kva = dm_kva; -	mod->req_pld_list_pa = dm_pa; -	dm_kva += buf_pool_sz; -	dm_pa += buf_pool_sz; -	memset(mod->req_pld_list_kva, 0, buf_pool_sz); - -	/* -	 * Initialize the fcxp rsp payload list -	 */ -	buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps; -	mod->rsp_pld_list_kva = dm_kva; -	mod->rsp_pld_list_pa = dm_pa; -	dm_kva += buf_pool_sz; -	dm_pa += buf_pool_sz; -	memset(mod->rsp_pld_list_kva, 0, buf_pool_sz); - -	bfa_meminfo_dma_virt(mi) = dm_kva; -	bfa_meminfo_dma_phys(mi) = dm_pa; -} - -static void -claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi) +claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)  {  	u16	i;  	struct bfa_fcxp_s *fcxp; -	fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi); +	fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);  	memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps); -	INIT_LIST_HEAD(&mod->fcxp_free_q); +	INIT_LIST_HEAD(&mod->fcxp_req_free_q); +	INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);  	INIT_LIST_HEAD(&mod->fcxp_active_q); +	INIT_LIST_HEAD(&mod->fcxp_req_unused_q); +	INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);  	mod->fcxp_list = fcxp; @@ -518,47 +466,67 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)  		fcxp->fcxp_mod = mod;  		fcxp->fcxp_tag = i; -		list_add_tail(&fcxp->qe, &mod->fcxp_free_q); +		if (i < (mod->num_fcxps / 2)) { +			list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q); +			fcxp->req_rsp = BFA_TRUE; +		} else { +			list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q); +			fcxp->req_rsp = BFA_FALSE; +		} +  		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);  		fcxp->reqq_waiting = BFA_FALSE;  		fcxp = fcxp + 1;  	} -	bfa_meminfo_kva(mi) = (void *)fcxp; +	bfa_mem_kva_curp(mod) = (void *)fcxp;  }  static void -bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, -		 u32 *dm_len) +bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo, +		struct bfa_s *bfa)  { -	u16	num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs; +	struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa); +	struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa); +	struct bfa_mem_dma_s *seg_ptr; +	u16	nsegs, idx, per_seg_fcxp; +	u16	num_fcxps = cfg->fwcfg.num_fcxp_reqs; +	u32	per_fcxp_sz; -	if (num_fcxp_reqs == 0) +	if (num_fcxps == 0)  		return; -	/* -	 * Account for req/rsp payload -	 */ -	*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;  	if (cfg->drvcfg.min_cfg) -		*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs; +		per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;  	else -		*dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs; +		per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ; + +	/* dma memory */ +	nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz); +	per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz); + +	bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) { +		if (num_fcxps >= per_seg_fcxp) { +			num_fcxps -= per_seg_fcxp; +			bfa_mem_dma_setup(minfo, seg_ptr, +				per_seg_fcxp * per_fcxp_sz); +		} else +			bfa_mem_dma_setup(minfo, seg_ptr, +				num_fcxps * per_fcxp_sz); +	} -	/* -	 * Account for fcxp structs -	 */ -	*ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs; +	/* kva memory */ +	bfa_mem_kva_setup(minfo, fcxp_kva, +		cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));  }  static void  bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) +		struct bfa_pcidev_s *pcidev)  {  	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); -	memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));  	mod->bfa = bfa;  	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs; @@ -569,10 +537,10 @@ bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	if (!cfg->drvcfg.min_cfg)  		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ; -	INIT_LIST_HEAD(&mod->wait_q); +	INIT_LIST_HEAD(&mod->req_wait_q); +	INIT_LIST_HEAD(&mod->rsp_wait_q); -	claim_fcxp_req_rsp_mem(mod, meminfo); -	claim_fcxps_mem(mod, meminfo); +	claim_fcxps_mem(mod);  }  static void @@ -597,6 +565,10 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)  	struct bfa_fcxp_s *fcxp;  	struct list_head	      *qe, *qen; +	/* Enqueue unused fcxp resources to free_q */ +	list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q); +	list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q); +  	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {  		fcxp = (struct bfa_fcxp_s *) qe;  		if (fcxp->caller == NULL) { @@ -612,11 +584,14 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)  }  static struct bfa_fcxp_s * -bfa_fcxp_get(struct bfa_fcxp_mod_s *fm) +bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)  {  	struct bfa_fcxp_s *fcxp; -	bfa_q_deq(&fm->fcxp_free_q, &fcxp); +	if (req) +		bfa_q_deq(&fm->fcxp_req_free_q, &fcxp); +	else +		bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);  	if (fcxp)  		list_add_tail(&fcxp->qe, &fm->fcxp_active_q); @@ -637,15 +612,15 @@ bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,  	       bfa_fcxp_get_sglen_t sglen_cbfn)  { -	bfa_assert(bfa != NULL); +	WARN_ON(bfa == NULL);  	bfa_trc(bfa, fcxp->fcxp_tag);  	if (n_sgles == 0) {  		*use_ibuf = 1;  	} else { -		bfa_assert(*sga_cbfn != NULL); -		bfa_assert(*sglen_cbfn != NULL); +		WARN_ON(*sga_cbfn == NULL); +		WARN_ON(*sglen_cbfn == NULL);  		*use_ibuf = 0;  		*r_sga_cbfn = sga_cbfn; @@ -657,7 +632,7 @@ bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,  		 * alloc required sgpgs  		 */  		if (n_sgles > BFI_SGE_INLINE) -			bfa_assert(0); +			WARN_ON(1);  	}  } @@ -671,7 +646,7 @@ bfa_fcxp_init(struct bfa_fcxp_s *fcxp,  	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)  { -	bfa_assert(bfa != NULL); +	WARN_ON(bfa == NULL);  	bfa_trc(bfa, fcxp->fcxp_tag); @@ -695,7 +670,11 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp)  	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;  	struct bfa_fcxp_wqe_s *wqe; -	bfa_q_deq(&mod->wait_q, &wqe); +	if (fcxp->req_rsp) +		bfa_q_deq(&mod->req_wait_q, &wqe); +	else +		bfa_q_deq(&mod->rsp_wait_q, &wqe); +  	if (wqe) {  		bfa_trc(mod->bfa, fcxp->fcxp_tag); @@ -708,9 +687,13 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp)  		return;  	} -	bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp)); +	WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));  	list_del(&fcxp->qe); -	list_add_tail(&fcxp->qe, &mod->fcxp_free_q); + +	if (fcxp->req_rsp) +		list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q); +	else +		list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);  }  static void @@ -757,7 +740,7 @@ hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)  	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag); -	bfa_assert(fcxp->send_cbfn != NULL); +	WARN_ON(fcxp->send_cbfn == NULL);  	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp); @@ -786,23 +769,6 @@ hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)  }  static void -hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa) -{ -	union bfi_addr_u      sga_zero = { {0} }; - -	sge->sg_len = reqlen; -	sge->flags = BFI_SGE_DATA_LAST; -	bfa_dma_addr_set(sge[0].sga, req_pa); -	bfa_sge_to_be(sge); -	sge++; - -	sge->sga = sga_zero; -	sge->sg_len = reqlen; -	sge->flags = BFI_SGE_PGDLEN; -	bfa_sge_to_be(sge); -} - -static void  hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,  		 struct fchs_s *fchs)  { @@ -882,7 +848,7 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)  	struct bfa_rport_s		*rport = reqi->bfa_rport;  	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ, -		    bfa_lpuid(bfa)); +		    bfa_fn_lpu(bfa));  	send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);  	if (rport) { @@ -896,7 +862,7 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)  	}  	send_req->vf_id = cpu_to_be16(reqi->vf_id); -	send_req->lp_tag = reqi->lp_tag; +	send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);  	send_req->class = reqi->class;  	send_req->rsp_timeout = rspi->rsp_timeout;  	send_req->cts = reqi->cts; @@ -909,18 +875,16 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)  	 * setup req sgles  	 */  	if (fcxp->use_ireqbuf == 1) { -		hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len, +		bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,  					BFA_FCXP_REQ_PLD_PA(fcxp));  	} else {  		if (fcxp->nreq_sgles > 0) { -			bfa_assert(fcxp->nreq_sgles == 1); -			hal_fcxp_set_local_sges(send_req->req_sge, -						reqi->req_tot_len, -						fcxp->req_sga_cbfn(fcxp->caller, -								   0)); +			WARN_ON(fcxp->nreq_sgles != 1); +			bfa_alen_set(&send_req->req_alen, reqi->req_tot_len, +				fcxp->req_sga_cbfn(fcxp->caller, 0));  		} else { -			bfa_assert(reqi->req_tot_len == 0); -			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0); +			WARN_ON(reqi->req_tot_len != 0); +			bfa_alen_set(&send_req->rsp_alen, 0, 0);  		}  	} @@ -928,37 +892,31 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)  	 * setup rsp sgles  	 */  	if (fcxp->use_irspbuf == 1) { -		bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ); +		WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ); -		hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen, +		bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,  					BFA_FCXP_RSP_PLD_PA(fcxp)); -  	} else {  		if (fcxp->nrsp_sgles > 0) { -			bfa_assert(fcxp->nrsp_sgles == 1); -			hal_fcxp_set_local_sges(send_req->rsp_sge, -						rspi->rsp_maxlen, -						fcxp->rsp_sga_cbfn(fcxp->caller, -								   0)); +			WARN_ON(fcxp->nrsp_sgles != 1); +			bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen, +				fcxp->rsp_sga_cbfn(fcxp->caller, 0)); +  		} else { -			bfa_assert(rspi->rsp_maxlen == 0); -			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0); +			WARN_ON(rspi->rsp_maxlen != 0); +			bfa_alen_set(&send_req->rsp_alen, 0, 0);  		}  	}  	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs); -	bfa_reqq_produce(bfa, BFA_REQQ_FCXP); +	bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);  	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));  	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));  }  /* - *  hal_fcxp_api BFA FCXP API - */ - -/*   * Allocate an FCXP instance to send a response or to send a request   * that has a response. Request/response buffers are allocated by caller.   * @@ -978,21 +936,23 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)   *				Address (given the sge index).   * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG   *				len (given the sge index). + * @param[in]	req		Allocated FCXP is used to send req or rsp? + *				request - BFA_TRUE, response - BFA_FALSE   *   * @return FCXP instance. NULL on failure.   */  struct bfa_fcxp_s * -bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles, -	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn, -	       bfa_fcxp_get_sglen_t req_sglen_cbfn, -	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn, -	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn) +bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles, +		int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn, +		bfa_fcxp_get_sglen_t req_sglen_cbfn, +		bfa_fcxp_get_sgaddr_t rsp_sga_cbfn, +		bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)  {  	struct bfa_fcxp_s *fcxp = NULL; -	bfa_assert(bfa != NULL); +	WARN_ON(bfa == NULL); -	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa)); +	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);  	if (fcxp == NULL)  		return NULL; @@ -1017,9 +977,9 @@ bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)  	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;  	void	*reqbuf; -	bfa_assert(fcxp->use_ireqbuf == 1); -	reqbuf = ((u8 *)mod->req_pld_list_kva) + -		fcxp->fcxp_tag * mod->req_pld_sz; +	WARN_ON(fcxp->use_ireqbuf != 1); +	reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag, +				mod->req_pld_sz + mod->rsp_pld_sz);  	return reqbuf;  } @@ -1042,17 +1002,19 @@ void *  bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)  {  	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; -	void	*rspbuf; +	void	*fcxp_buf; + +	WARN_ON(fcxp->use_irspbuf != 1); -	bfa_assert(fcxp->use_irspbuf == 1); +	fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag, +				mod->req_pld_sz + mod->rsp_pld_sz); -	rspbuf = ((u8 *)mod->rsp_pld_list_kva) + -		fcxp->fcxp_tag * mod->rsp_pld_sz; -	return rspbuf; +	/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */ +	return ((u8 *) fcxp_buf) + mod->req_pld_sz;  }  /* - *		Free the BFA FCXP + * Free the BFA FCXP   *   * @param[in]	fcxp			BFA fcxp pointer   * @@ -1063,7 +1025,7 @@ bfa_fcxp_free(struct bfa_fcxp_s *fcxp)  {  	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; -	bfa_assert(fcxp != NULL); +	WARN_ON(fcxp == NULL);  	bfa_trc(mod->bfa, fcxp->fcxp_tag);  	bfa_fcxp_put(fcxp);  } @@ -1075,7 +1037,7 @@ bfa_fcxp_free(struct bfa_fcxp_s *fcxp)   * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports   * @param[in]	vf_id	virtual Fabric ID   * @param[in]	lp_tag	lport tag - * @param[in]	cts	use Continous sequence + * @param[in]	cts	use Continuous sequence   * @param[in]	cos	fc Class of Service   * @param[in]	reqlen	request length, does not include FCHS length   * @param[in]	fchs	fc Header Pointer. The header content will be copied @@ -1142,22 +1104,25 @@ bfa_status_t  bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)  {  	bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag); -	bfa_assert(0); +	WARN_ON(1);  	return BFA_STATUS_OK;  }  void -bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe, +bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,  	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,  	       void *caller, int nreq_sgles,  	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,  	       bfa_fcxp_get_sglen_t req_sglen_cbfn,  	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn, -	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn) +	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)  {  	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); -	bfa_assert(list_empty(&mod->fcxp_free_q)); +	if (req) +		WARN_ON(!list_empty(&mod->fcxp_req_free_q)); +	else +		WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));  	wqe->alloc_cbfn = alloc_cbfn;  	wqe->alloc_cbarg = alloc_cbarg; @@ -1170,7 +1135,10 @@ bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,  	wqe->rsp_sga_cbfn = rsp_sga_cbfn;  	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn; -	list_add_tail(&wqe->qe, &mod->wait_q); +	if (req) +		list_add_tail(&wqe->qe, &mod->req_wait_q); +	else +		list_add_tail(&wqe->qe, &mod->rsp_wait_q);  }  void @@ -1178,7 +1146,8 @@ bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)  {  	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); -	bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe)); +	WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) || +		!bfa_q_is_on_q(&mod->rsp_wait_q, wqe));  	list_del(&wqe->qe);  } @@ -1199,12 +1168,6 @@ bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)  	fcxp->send_cbfn = bfa_fcxp_null_comp;  } - - -/* - *  hal_fcxp_public BFA FCXP public functions - */ -  void  bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)  { @@ -1215,7 +1178,7 @@ bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)  	default:  		bfa_trc(bfa, msg->mhdr.msg_id); -		bfa_assert(0); +		WARN_ON(1);  	}  } @@ -1227,6 +1190,23 @@ bfa_fcxp_get_maxrsp(struct bfa_s *bfa)  	return mod->rsp_pld_sz;  } +void +bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw) +{ +	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa); +	struct list_head	*qe; +	int	i; + +	for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) { +		if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) { +			bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe); +			list_add_tail(qe, &mod->fcxp_req_unused_q); +		} else { +			bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe); +			list_add_tail(qe, &mod->fcxp_rsp_unused_q); +		} +	} +}  /*   *  BFA LPS state machine functions @@ -1238,7 +1218,7 @@ bfa_fcxp_get_maxrsp(struct bfa_s *bfa)  static void  bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)  { -	bfa_trc(lps->bfa, lps->lp_tag); +	bfa_trc(lps->bfa, lps->bfa_tag);  	bfa_trc(lps->bfa, event);  	switch (event) { @@ -1278,6 +1258,12 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)  		 * Just ignore  		 */  		break; +	case BFA_LPS_SM_SET_N2N_PID: +		/* +		 * When topology is set to loop, bfa_lps_set_n2n_pid() sends +		 * this event. Ignore this event. +		 */ +		break;  	default:  		bfa_sm_fault(lps->bfa, event); @@ -1290,7 +1276,7 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)  static void  bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)  { -	bfa_trc(lps->bfa, lps->lp_tag); +	bfa_trc(lps->bfa, lps->bfa_tag);  	bfa_trc(lps->bfa, event);  	switch (event) { @@ -1303,6 +1289,12 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)  			else  				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,  					BFA_PL_EID_LOGIN, 0, "FLOGI Accept"); +			/* If N2N, send the assigned PID to FW */ +			bfa_trc(lps->bfa, lps->fport); +			bfa_trc(lps->bfa, lps->lp_pid); + +			if (!lps->fport && lps->lp_pid) +				bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);  		} else {  			bfa_sm_set_state(lps, bfa_lps_sm_init);  			if (lps->fdisc) @@ -1318,9 +1310,15 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)  		break;  	case BFA_LPS_SM_OFFLINE: +	case BFA_LPS_SM_DELETE:  		bfa_sm_set_state(lps, bfa_lps_sm_init);  		break; +	case BFA_LPS_SM_SET_N2N_PID: +		bfa_trc(lps->bfa, lps->fport); +		bfa_trc(lps->bfa, lps->lp_pid); +		break; +  	default:  		bfa_sm_fault(lps->bfa, event);  	} @@ -1332,15 +1330,17 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)  static void  bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)  { -	bfa_trc(lps->bfa, lps->lp_tag); +	bfa_trc(lps->bfa, lps->bfa_tag);  	bfa_trc(lps->bfa, event);  	switch (event) {  	case BFA_LPS_SM_RESUME:  		bfa_sm_set_state(lps, bfa_lps_sm_login); +		bfa_lps_send_login(lps);  		break;  	case BFA_LPS_SM_OFFLINE: +	case BFA_LPS_SM_DELETE:  		bfa_sm_set_state(lps, bfa_lps_sm_init);  		bfa_reqq_wcancel(&lps->wqe);  		break; @@ -1364,7 +1364,7 @@ bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)  static void  bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)  { -	bfa_trc(lps->bfa, lps->lp_tag); +	bfa_trc(lps->bfa, lps->bfa_tag);  	bfa_trc(lps->bfa, event);  	switch (event) { @@ -1389,9 +1389,59 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)  			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");  		break; +	case BFA_LPS_SM_SET_N2N_PID: +		if (bfa_reqq_full(lps->bfa, lps->reqq)) { +			bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait); +			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe); +		} else +			bfa_lps_send_set_n2n_pid(lps); +		break; + +	case BFA_LPS_SM_OFFLINE: +	case BFA_LPS_SM_DELETE: +		bfa_sm_set_state(lps, bfa_lps_sm_init); +		break; + +	default: +		bfa_sm_fault(lps->bfa, event); +	} +} + +/* + * login complete + */ +static void +bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event) +{ +	bfa_trc(lps->bfa, lps->bfa_tag); +	bfa_trc(lps->bfa, event); + +	switch (event) { +	case BFA_LPS_SM_RESUME: +		bfa_sm_set_state(lps, bfa_lps_sm_online); +		bfa_lps_send_set_n2n_pid(lps); +		break; + +	case BFA_LPS_SM_LOGOUT: +		bfa_sm_set_state(lps, bfa_lps_sm_logowait); +		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS, +			BFA_PL_EID_LOGO, 0, "Logout"); +		break; + +	case BFA_LPS_SM_RX_CVL: +		bfa_sm_set_state(lps, bfa_lps_sm_init); +		bfa_reqq_wcancel(&lps->wqe); + +		/* Let the vport module know about this event */ +		bfa_lps_cvl_event(lps); +		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS, +			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx"); +		break; +  	case BFA_LPS_SM_OFFLINE:  	case BFA_LPS_SM_DELETE:  		bfa_sm_set_state(lps, bfa_lps_sm_init); +		bfa_reqq_wcancel(&lps->wqe);  		break;  	default: @@ -1405,16 +1455,17 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)  static void  bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)  { -	bfa_trc(lps->bfa, lps->lp_tag); +	bfa_trc(lps->bfa, lps->bfa_tag);  	bfa_trc(lps->bfa, event);  	switch (event) {  	case BFA_LPS_SM_FWRSP: +	case BFA_LPS_SM_OFFLINE:  		bfa_sm_set_state(lps, bfa_lps_sm_init);  		bfa_lps_logout_comp(lps);  		break; -	case BFA_LPS_SM_OFFLINE: +	case BFA_LPS_SM_DELETE:  		bfa_sm_set_state(lps, bfa_lps_sm_init);  		break; @@ -1429,7 +1480,7 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)  static void  bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)  { -	bfa_trc(lps->bfa, lps->lp_tag); +	bfa_trc(lps->bfa, lps->bfa_tag);  	bfa_trc(lps->bfa, event);  	switch (event) { @@ -1439,6 +1490,7 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)  		break;  	case BFA_LPS_SM_OFFLINE: +	case BFA_LPS_SM_DELETE:  		bfa_sm_set_state(lps, bfa_lps_sm_init);  		bfa_reqq_wcancel(&lps->wqe);  		break; @@ -1458,13 +1510,17 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)   * return memory requirement   */  static void -bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, -	u32 *dm_len) +bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo, +		struct bfa_s *bfa)  { +	struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa); +  	if (cfg->drvcfg.min_cfg) -		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS; +		bfa_mem_kva_setup(minfo, lps_kva, +			sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);  	else -		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS; +		bfa_mem_kva_setup(minfo, lps_kva, +			sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);  }  /* @@ -1472,28 +1528,28 @@ bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,   */  static void  bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -	struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) +	struct bfa_pcidev_s *pcidev)  {  	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);  	struct bfa_lps_s	*lps;  	int			i; -	memset(mod, 0, sizeof(struct bfa_lps_mod_s));  	mod->num_lps = BFA_LPS_MAX_LPORTS;  	if (cfg->drvcfg.min_cfg)  		mod->num_lps = BFA_LPS_MIN_LPORTS;  	else  		mod->num_lps = BFA_LPS_MAX_LPORTS; -	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo); +	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod); -	bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s); +	bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);  	INIT_LIST_HEAD(&mod->lps_free_q);  	INIT_LIST_HEAD(&mod->lps_active_q); +	INIT_LIST_HEAD(&mod->lps_login_q);  	for (i = 0; i < mod->num_lps; i++, lps++) {  		lps->bfa	= bfa; -		lps->lp_tag	= (u8) i; +		lps->bfa_tag	= (u8) i;  		lps->reqq	= BFA_REQQ_LPS;  		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);  		list_add_tail(&lps->qe, &mod->lps_free_q); @@ -1529,6 +1585,11 @@ bfa_lps_iocdisable(struct bfa_s *bfa)  		lps = (struct bfa_lps_s *) qe;  		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);  	} +	list_for_each_safe(qe, qen, &mod->lps_login_q) { +		lps = (struct bfa_lps_s *) qe; +		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE); +	} +	list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);  }  /* @@ -1540,15 +1601,17 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)  	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);  	struct bfa_lps_s	*lps; -	bfa_assert(rsp->lp_tag < mod->num_lps); -	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); +	WARN_ON(rsp->bfa_tag >= mod->num_lps); +	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);  	lps->status = rsp->status;  	switch (rsp->status) {  	case BFA_STATUS_OK: +		lps->fw_tag	= rsp->fw_tag;  		lps->fport	= rsp->f_port; +		if (lps->fport) +			lps->lp_pid = rsp->lp_pid;  		lps->npiv_en	= rsp->npiv_en; -		lps->lp_pid	= rsp->lp_pid;  		lps->pr_bbcred	= be16_to_cpu(rsp->bb_credit);  		lps->pr_pwwn	= rsp->port_name;  		lps->pr_nwwn	= rsp->node_name; @@ -1570,14 +1633,46 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)  		break; +	case BFA_STATUS_VPORT_MAX: +		if (rsp->ext_status) +			bfa_lps_no_res(lps, rsp->ext_status); +		break; +  	default:  		/* Nothing to do with other status */  		break;  	} +	list_del(&lps->qe); +	list_add_tail(&lps->qe, &mod->lps_active_q);  	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);  } +static void +bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count) +{ +	struct bfa_s		*bfa = first_lps->bfa; +	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa); +	struct list_head	*qe, *qe_next; +	struct bfa_lps_s	*lps; + +	bfa_trc(bfa, count); + +	qe = bfa_q_next(first_lps); + +	while (count && qe) { +		qe_next = bfa_q_next(qe); +		lps = (struct bfa_lps_s *)qe; +		bfa_trc(bfa, lps->bfa_tag); +		lps->status = first_lps->status; +		list_del(&lps->qe); +		list_add_tail(&lps->qe, &mod->lps_active_q); +		bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP); +		qe = qe_next; +		count--; +	} +} +  /*   * Firmware logout response   */ @@ -1587,8 +1682,8 @@ bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)  	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);  	struct bfa_lps_s	*lps; -	bfa_assert(rsp->lp_tag < mod->num_lps); -	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); +	WARN_ON(rsp->bfa_tag >= mod->num_lps); +	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);  	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);  } @@ -1602,7 +1697,7 @@ bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)  	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);  	struct bfa_lps_s	*lps; -	lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag); +	lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);  	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);  } @@ -1637,15 +1732,16 @@ bfa_lps_free(struct bfa_lps_s *lps)  static void  bfa_lps_send_login(struct bfa_lps_s *lps)  { +	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);  	struct bfi_lps_login_req_s	*m;  	m = bfa_reqq_next(lps->bfa, lps->reqq); -	bfa_assert(m); +	WARN_ON(!m);  	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ, -		bfa_lpuid(lps->bfa)); +		bfa_fn_lpu(lps->bfa)); -	m->lp_tag	= lps->lp_tag; +	m->bfa_tag	= lps->bfa_tag;  	m->alpa		= lps->alpa;  	m->pdu_size	= cpu_to_be16(lps->pdusz);  	m->pwwn		= lps->pwwn; @@ -1653,7 +1749,9 @@ bfa_lps_send_login(struct bfa_lps_s *lps)  	m->fdisc	= lps->fdisc;  	m->auth_en	= lps->auth_en; -	bfa_reqq_produce(lps->bfa, lps->reqq); +	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh); +	list_del(&lps->qe); +	list_add_tail(&lps->qe, &mod->lps_login_q);  }  /* @@ -1665,14 +1763,33 @@ bfa_lps_send_logout(struct bfa_lps_s *lps)  	struct bfi_lps_logout_req_s *m;  	m = bfa_reqq_next(lps->bfa, lps->reqq); -	bfa_assert(m); +	WARN_ON(!m);  	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ, -		bfa_lpuid(lps->bfa)); +		bfa_fn_lpu(lps->bfa)); -	m->lp_tag    = lps->lp_tag; +	m->fw_tag = lps->fw_tag;  	m->port_name = lps->pwwn; -	bfa_reqq_produce(lps->bfa, lps->reqq); +	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh); +} + +/* + * send n2n pid set request to firmware + */ +static void +bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps) +{ +	struct bfi_lps_n2n_pid_req_s *m; + +	m = bfa_reqq_next(lps->bfa, lps->reqq); +	WARN_ON(!m); + +	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ, +		bfa_fn_lpu(lps->bfa)); + +	m->fw_tag = lps->fw_tag; +	m->lp_pid = lps->lp_pid; +	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);  }  /* @@ -1723,6 +1840,8 @@ bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)  	if (lps->fdisc)  		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg); +	else +		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);  }  /* @@ -1853,14 +1972,6 @@ bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,  	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);  } -/* - * Initiate a lport logout (flogi). - */ -void -bfa_lps_flogo(struct bfa_lps_s *lps) -{ -	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT); -}  /*   * Initiate a lport FDSIC logout. @@ -1871,23 +1982,12 @@ bfa_lps_fdisclogo(struct bfa_lps_s *lps)  	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);  } -/* - * Discard a pending login request -- should be called only for - * link down handling. - */ -void -bfa_lps_discard(struct bfa_lps_s *lps) -{ -	bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE); -} - -/* - * Return lport services tag - */  u8 -bfa_lps_get_tag(struct bfa_lps_s *lps) +bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)  { -	return lps->lp_tag; +	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa); + +	return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;  }  /* @@ -1902,62 +2002,13 @@ bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)  	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {  		if (lps->lp_pid == pid) -			return lps->lp_tag; +			return lps->bfa_tag;  	}  	/* Return base port tag anyway */  	return 0;  } -/* - * return if fabric login indicates support for NPIV - */ -bfa_boolean_t -bfa_lps_is_npiv_en(struct bfa_lps_s *lps) -{ -	return lps->npiv_en; -} - -/* - * Return TRUE if attached to F-Port, else return FALSE - */ -bfa_boolean_t -bfa_lps_is_fport(struct bfa_lps_s *lps) -{ -	return lps->fport; -} - -/* - * Return TRUE if attached to a Brocade Fabric - */ -bfa_boolean_t -bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps) -{ -	return lps->brcd_switch; -} -/* - * return TRUE if authentication is required - */ -bfa_boolean_t -bfa_lps_is_authreq(struct bfa_lps_s *lps) -{ -	return lps->auth_req; -} - -bfa_eproto_status_t -bfa_lps_get_extstatus(struct bfa_lps_s *lps) -{ -	return lps->ext_status; -} - -/* - * return port id assigned to the lport - */ -u32 -bfa_lps_get_pid(struct bfa_lps_s *lps) -{ -	return lps->lp_pid; -}  /*   * return port id assigned to the base lport @@ -1971,57 +2022,16 @@ bfa_lps_get_base_pid(struct bfa_s *bfa)  }  /* - * Return bb_credit assigned in FLOGI response - */ -u16 -bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps) -{ -	return lps->pr_bbcred; -} - -/* - * Return peer port name - */ -wwn_t -bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps) -{ -	return lps->pr_pwwn; -} - -/* - * Return peer node name - */ -wwn_t -bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps) -{ -	return lps->pr_nwwn; -} - -/* - * return reason code if login request is rejected - */ -u8 -bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps) -{ -	return lps->lsrjt_rsn; -} - -/* - * return explanation code if login request is rejected + * Set PID in case of n2n (which is assigned during PLOGI)   */ -u8 -bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps) +void +bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)  { -	return lps->lsrjt_expl; -} +	bfa_trc(lps->bfa, lps->bfa_tag); +	bfa_trc(lps->bfa, n2n_pid); -/* - * Return fpma/spma MAC for lport - */ -mac_t -bfa_lps_get_lp_mac(struct bfa_lps_s *lps) -{ -	return lps->lp_mac; +	lps->lp_pid = n2n_pid; +	bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);  }  /* @@ -2036,24 +2046,42 @@ bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  	msg.msg = m;  	switch (m->mhdr.msg_id) { -	case BFI_LPS_H2I_LOGIN_RSP: +	case BFI_LPS_I2H_LOGIN_RSP:  		bfa_lps_login_rsp(bfa, msg.login_rsp);  		break; -	case BFI_LPS_H2I_LOGOUT_RSP: +	case BFI_LPS_I2H_LOGOUT_RSP:  		bfa_lps_logout_rsp(bfa, msg.logout_rsp);  		break; -	case BFI_LPS_H2I_CVL_EVENT: +	case BFI_LPS_I2H_CVL_EVENT:  		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);  		break;  	default:  		bfa_trc(bfa, m->mhdr.msg_id); -		bfa_assert(0); +		WARN_ON(1);  	}  } +static void +bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event) +{ +	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad; +	struct bfa_aen_entry_s  *aen_entry; + +	bfad_get_aen_entry(bfad, aen_entry); +	if (!aen_entry) +		return; + +	aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa); +	aen_entry->aen_data.port.pwwn = fcport->pwwn; + +	/* Send the AEN notification */ +	bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq, +				  BFA_AEN_CAT_PORT, event); +} +  /*   * FC PORT state machine functions   */ @@ -2068,6 +2096,8 @@ bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,  		/*  		 * Start event after IOC is configured and BFA is started.  		 */ +		fcport->use_flash_cfg = BFA_TRUE; +  		if (bfa_fcport_send_enable(fcport)) {  			bfa_trc(fcport->bfa, BFA_TRUE);  			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling); @@ -2138,8 +2168,9 @@ bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);  		break;  	case BFA_FCPORT_SM_LINKUP: @@ -2155,6 +2186,12 @@ bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,  		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);  		break; +	case BFA_FCPORT_SM_FAA_MISCONFIG: +		bfa_fcport_reset_linkinfo(fcport); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig); +		break; +  	default:  		bfa_sm_fault(fcport->bfa, event);  	} @@ -2178,7 +2215,7 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,  		bfa_fcport_update_linkinfo(fcport);  		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup); -		bfa_assert(fcport->event_cbfn); +		WARN_ON(!fcport->event_cbfn);  		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);  		break; @@ -2198,8 +2235,9 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);  		break;  	case BFA_FCPORT_SM_STOP: @@ -2210,6 +2248,12 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,  		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);  		break; +	case BFA_FCPORT_SM_FAA_MISCONFIG: +		bfa_fcport_reset_linkinfo(fcport); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig); +		break; +  	default:  		bfa_sm_fault(fcport->bfa, event);  	} @@ -2229,17 +2273,17 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,  	case BFA_FCPORT_SM_LINKUP:  		bfa_fcport_update_linkinfo(fcport);  		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup); -		bfa_assert(fcport->event_cbfn); +		WARN_ON(!fcport->event_cbfn);  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");  		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {  			bfa_trc(fcport->bfa, -				pevent->link_state.vc_fcf.fcf.fipenabled); +				pevent->link_state.attr.vc_fcf.fcf.fipenabled);  			bfa_trc(fcport->bfa, -				pevent->link_state.vc_fcf.fcf.fipfailed); +				pevent->link_state.attr.vc_fcf.fcf.fipfailed); -			if (pevent->link_state.vc_fcf.fcf.fipfailed) +			if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)  				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  					BFA_PL_EID_FIP_FCF_DISC, 0,  					"FIP FCF Discovery Failed"); @@ -2251,8 +2295,14 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,  		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port online: WWN = %s\n", pwwn_buf); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE); + +		/* If QoS is enabled and it is not online, send AEN */ +		if (fcport->cfg.qos_enabled && +		    fcport->qos_attr.state != BFA_QOS_ONLINE) +			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);  		break;  	case BFA_FCPORT_SM_LINKDOWN: @@ -2277,8 +2327,9 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);  		break;  	case BFA_FCPORT_SM_STOP: @@ -2289,6 +2340,12 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,  		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);  		break; +	case BFA_FCPORT_SM_FAA_MISCONFIG: +		bfa_fcport_reset_linkinfo(fcport); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig); +		break; +  	default:  		bfa_sm_fault(fcport->bfa, event);  	} @@ -2322,10 +2379,12 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port offline: WWN = %s\n", pwwn_buf); -		BFA_LOG(KERN_INFO, bfad, log_level, +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE); +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port disabled: WWN = %s\n", pwwn_buf); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);  		break;  	case BFA_FCPORT_SM_LINKDOWN: @@ -2335,26 +2394,32 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");  		wwn2str(pwwn_buf, fcport->pwwn); -		if (BFA_PORT_IS_DISABLED(fcport->bfa)) -			BFA_LOG(KERN_INFO, bfad, log_level, +		if (BFA_PORT_IS_DISABLED(fcport->bfa)) { +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Base port offline: WWN = %s\n", pwwn_buf); -		else -			BFA_LOG(KERN_ERR, bfad, log_level, +			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE); +		} else { +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Base port (WWN = %s) "  				"lost fabric connectivity\n", pwwn_buf); +			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		}  		break;  	case BFA_FCPORT_SM_STOP:  		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);  		bfa_fcport_reset_linkinfo(fcport);  		wwn2str(pwwn_buf, fcport->pwwn); -		if (BFA_PORT_IS_DISABLED(fcport->bfa)) -			BFA_LOG(KERN_INFO, bfad, log_level, +		if (BFA_PORT_IS_DISABLED(fcport->bfa)) { +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Base port offline: WWN = %s\n", pwwn_buf); -		else -			BFA_LOG(KERN_ERR, bfad, log_level, +			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE); +		} else { +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Base port (WWN = %s) "  				"lost fabric connectivity\n", pwwn_buf); +			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		}  		break;  	case BFA_FCPORT_SM_HWFAIL: @@ -2362,13 +2427,22 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,  		bfa_fcport_reset_linkinfo(fcport);  		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);  		wwn2str(pwwn_buf, fcport->pwwn); -		if (BFA_PORT_IS_DISABLED(fcport->bfa)) -			BFA_LOG(KERN_INFO, bfad, log_level, +		if (BFA_PORT_IS_DISABLED(fcport->bfa)) { +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"Base port offline: WWN = %s\n", pwwn_buf); -		else -			BFA_LOG(KERN_ERR, bfad, log_level, +			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE); +		} else { +			BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"Base port (WWN = %s) "  				"lost fabric connectivity\n", pwwn_buf); +			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		} +		break; + +	case BFA_FCPORT_SM_FAA_MISCONFIG: +		bfa_fcport_reset_linkinfo(fcport); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);  		break;  	default: @@ -2416,6 +2490,12 @@ bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,  		bfa_reqq_wcancel(&fcport->reqq_wait);  		break; +	case BFA_FCPORT_SM_FAA_MISCONFIG: +		bfa_fcport_reset_linkinfo(fcport); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT); +		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig); +		break; +  	default:  		bfa_sm_fault(fcport->bfa, event);  	} @@ -2497,8 +2577,9 @@ bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port enabled: WWN = %s\n", pwwn_buf); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);  		break;  	case BFA_FCPORT_SM_STOP: @@ -2551,8 +2632,9 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,  		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,  				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");  		wwn2str(pwwn_buf, fcport->pwwn); -		BFA_LOG(KERN_INFO, bfad, log_level, +		BFA_LOG(KERN_INFO, bfad, bfa_log_level,  			"Base port enabled: WWN = %s\n", pwwn_buf); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);  		break;  	case BFA_FCPORT_SM_DISABLE: @@ -2565,6 +2647,14 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,  		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);  		break; +	case BFA_FCPORT_SM_DPORTENABLE: +		bfa_sm_set_state(fcport, bfa_fcport_sm_dport); +		break; + +	case BFA_FCPORT_SM_DDPORTENABLE: +		bfa_sm_set_state(fcport, bfa_fcport_sm_ddport); +		break; +  	default:  		bfa_sm_fault(fcport->bfa, event);  	} @@ -2645,6 +2735,115 @@ bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,  	}  } +static void +bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event) +{ +	bfa_trc(fcport->bfa, event); + +	switch (event) { +	case BFA_FCPORT_SM_DPORTENABLE: +	case BFA_FCPORT_SM_DISABLE: +	case BFA_FCPORT_SM_ENABLE: +	case BFA_FCPORT_SM_START: +		/* +		 * Ignore event for a port that is dport +		 */ +		break; + +	case BFA_FCPORT_SM_STOP: +		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped); +		break; + +	case BFA_FCPORT_SM_HWFAIL: +		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail); +		break; + +	case BFA_FCPORT_SM_DPORTDISABLE: +		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled); +		break; + +	default: +		bfa_sm_fault(fcport->bfa, event); +	} +} + +static void +bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport, +			enum bfa_fcport_sm_event event) +{ +	bfa_trc(fcport->bfa, event); + +	switch (event) { +	case BFA_FCPORT_SM_DISABLE: +	case BFA_FCPORT_SM_DDPORTDISABLE: +		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled); +		break; + +	case BFA_FCPORT_SM_DPORTENABLE: +	case BFA_FCPORT_SM_DPORTDISABLE: +	case BFA_FCPORT_SM_ENABLE: +	case BFA_FCPORT_SM_START: +		/** +		 * Ignore event for a port that is ddport +		 */ +		break; + +	case BFA_FCPORT_SM_STOP: +		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped); +		break; + +	case BFA_FCPORT_SM_HWFAIL: +		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail); +		break; + +	default: +		bfa_sm_fault(fcport->bfa, event); +	} +} + +static void +bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport, +			    enum bfa_fcport_sm_event event) +{ +	bfa_trc(fcport->bfa, event); + +	switch (event) { +	case BFA_FCPORT_SM_DPORTENABLE: +	case BFA_FCPORT_SM_ENABLE: +	case BFA_FCPORT_SM_START: +		/* +		 * Ignore event for a port as there is FAA misconfig +		 */ +		break; + +	case BFA_FCPORT_SM_DISABLE: +		if (bfa_fcport_send_disable(fcport)) +			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling); +		else +			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait); + +		bfa_fcport_reset_linkinfo(fcport); +		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE); +		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL, +			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable"); +		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE); +		break; + +	case BFA_FCPORT_SM_STOP: +		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped); +		break; + +	case BFA_FCPORT_SM_HWFAIL: +		bfa_fcport_reset_linkinfo(fcport); +		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE); +		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown); +		break; + +	default: +		bfa_sm_fault(fcport->bfa, event); +	} +} +  /*   * Link state is down   */ @@ -2803,12 +3002,6 @@ bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,  	}  } - - -/* - *  hal_port_private - */ -  static void  __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)  { @@ -2839,7 +3032,7 @@ bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,  		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);  		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  	}  } @@ -2862,10 +3055,12 @@ bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)  							BFA_CACHELINE_SZ))  static void -bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, -		u32 *dm_len) +bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo, +		   struct bfa_s *bfa)  { -	*dm_len += FCPORT_STATS_DMA_SZ; +	struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa); + +	bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);  }  static void @@ -2877,23 +3072,14 @@ bfa_fcport_qresume(void *cbarg)  }  static void -bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo) +bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)  { -	u8		*dm_kva; -	u64	dm_pa; - -	dm_kva = bfa_meminfo_dma_virt(meminfo); -	dm_pa  = bfa_meminfo_dma_phys(meminfo); - -	fcport->stats_kva = dm_kva; -	fcport->stats_pa  = dm_pa; -	fcport->stats	  = (union bfa_fcport_stats_u *) dm_kva; +	struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma; -	dm_kva += FCPORT_STATS_DMA_SZ; -	dm_pa  += FCPORT_STATS_DMA_SZ; - -	bfa_meminfo_dma_virt(meminfo) = dm_kva; -	bfa_meminfo_dma_phys(meminfo) = dm_pa; +	fcport->stats_kva = bfa_mem_dma_virt(fcport_dma); +	fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma); +	fcport->stats = (union bfa_fcport_stats_u *) +				bfa_mem_dma_virt(fcport_dma);  }  /* @@ -2901,18 +3087,17 @@ bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)   */  static void  bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) +		struct bfa_pcidev_s *pcidev)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);  	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;  	struct bfa_fcport_ln_s *ln = &fcport->ln; -	struct bfa_timeval_s tv; +	struct timeval tv; -	memset(fcport, 0, sizeof(struct bfa_fcport_s));  	fcport->bfa = bfa;  	ln->fcport = fcport; -	bfa_fcport_mem_claim(fcport, meminfo); +	bfa_fcport_mem_claim(fcport);  	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);  	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn); @@ -2920,8 +3105,9 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	/*  	 * initialize time stamp for stats reset  	 */ -	bfa_os_gettimeofday(&tv); +	do_gettimeofday(&tv);  	fcport->stats_reset_time = tv.tv_sec; +	fcport->stats_dma_ready = BFA_FALSE;  	/*  	 * initialize and set default configuration @@ -2932,6 +3118,14 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	port_cfg->maxfrsize = 0;  	port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS; +	port_cfg->qos_bw.high = BFA_QOS_BW_HIGH; +	port_cfg->qos_bw.med = BFA_QOS_BW_MED; +	port_cfg->qos_bw.low = BFA_QOS_BW_LOW; + +	fcport->fec_state = BFA_FEC_OFFLINE; + +	INIT_LIST_HEAD(&fcport->stats_pending_q); +	INIT_LIST_HEAD(&fcport->statsclr_pending_q);  	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);  } @@ -2972,6 +3166,21 @@ bfa_fcport_iocdisable(struct bfa_s *bfa)  	bfa_trunk_iocdisable(bfa);  } +/* + * Update loop info in fcport for SCN online + */ +static void +bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport, +			struct bfa_fcport_loop_info_s *loop_info) +{ +	fcport->myalpa = loop_info->myalpa; +	fcport->alpabm_valid = +			loop_info->alpabm_val; +	memcpy(fcport->alpabm.alpa_bm, +			loop_info->alpabm.alpa_bm, +			sizeof(struct fc_alpabm_s)); +} +  static void  bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)  { @@ -2981,12 +3190,20 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)  	fcport->speed = pevent->link_state.speed;  	fcport->topology = pevent->link_state.topology; -	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) -		fcport->myalpa = 0; +	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) { +		bfa_fcport_update_loop_info(fcport, +				&pevent->link_state.attr.loop_info); +		return; +	}  	/* QoS Details */  	fcport->qos_attr = pevent->link_state.qos_attr; -	fcport->qos_vc_attr = pevent->link_state.vc_fcf.qos_vc_attr; +	fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr; + +	if (fcport->cfg.bb_cr_enabled) +		fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr; + +	fcport->fec_state = pevent->link_state.fec_state;  	/*  	 * update trunk state if applicable @@ -2995,7 +3212,8 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)  		trunk->attr.state = BFA_TRUNK_DISABLED;  	/* update FCoE specific */ -	fcport->fcoe_vlan = be16_to_cpu(pevent->link_state.vc_fcf.fcf.vlan); +	fcport->fcoe_vlan = +		be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);  	bfa_trc(fcport->bfa, fcport->speed);  	bfa_trc(fcport->bfa, fcport->topology); @@ -3006,6 +3224,7 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)  {  	fcport->speed = BFA_PORT_SPEED_UNKNOWN;  	fcport->topology = BFA_PORT_TOPOLOGY_NONE; +	fcport->fec_state = BFA_FEC_OFFLINE;  }  /* @@ -3033,12 +3252,13 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport)  	}  	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ, -			bfa_lpuid(fcport->bfa)); +			bfa_fn_lpu(fcport->bfa));  	m->nwwn = fcport->nwwn;  	m->pwwn = fcport->pwwn;  	m->port_cfg = fcport->cfg;  	m->msgtag = fcport->msgtag;  	m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize); +	 m->use_flash_cfg = fcport->use_flash_cfg;  	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);  	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);  	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi); @@ -3046,7 +3266,7 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport)  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT); +	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);  	return BFA_TRUE;  } @@ -3075,13 +3295,13 @@ bfa_fcport_send_disable(struct bfa_fcport_s *fcport)  	}  	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ, -			bfa_lpuid(fcport->bfa)); +			bfa_fn_lpu(fcport->bfa));  	m->msgtag = fcport->msgtag;  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT); +	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);  	return BFA_TRUE;  } @@ -3089,45 +3309,19 @@ bfa_fcport_send_disable(struct bfa_fcport_s *fcport)  static void  bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)  { -	fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc); -	fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc); +	fcport->pwwn = fcport->bfa->ioc.attr->pwwn; +	fcport->nwwn = fcport->bfa->ioc.attr->nwwn;  	bfa_trc(fcport->bfa, fcport->pwwn);  	bfa_trc(fcport->bfa, fcport->nwwn);  }  static void -bfa_fcport_send_txcredit(void *port_cbarg) -{ - -	struct bfa_fcport_s *fcport = port_cbarg; -	struct bfi_fcport_set_svc_params_req_s *m; - -	/* -	 * check for room in queue to send request now -	 */ -	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT); -	if (!m) { -		bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit); -		return; -	} - -	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ, -			bfa_lpuid(fcport->bfa)); -	m->tx_bbcredit = cpu_to_be16((u16)fcport->cfg.tx_bbcredit); - -	/* -	 * queue I/O message to firmware -	 */ -	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT); -} - -static void  bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,  	struct bfa_qos_stats_s *s)  {  	u32	*dip = (u32 *) d; -	u32	*sip = (u32 *) s; +	__be32	*sip = (__be32 *) s;  	int		i;  	/* Now swap the 32 bit fields */ @@ -3140,12 +3334,12 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,  	struct bfa_fcoe_stats_s *s)  {  	u32	*dip = (u32 *) d; -	u32	*sip = (u32 *) s; +	__be32	*sip = (__be32 *) s;  	int		i;  	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));  	     i = i + 2) { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  		dip[i] = be32_to_cpu(sip[i]);  		dip[i + 1] = be32_to_cpu(sip[i + 1]);  #else @@ -3158,30 +3352,38 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,  static void  __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)  { -	struct bfa_fcport_s *fcport = cbarg; +	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg; +	struct bfa_cb_pending_q_s *cb; +	struct list_head *qe, *qen; +	union bfa_fcport_stats_u *ret;  	if (complete) { -		if (fcport->stats_status == BFA_STATUS_OK) { -			struct bfa_timeval_s tv; - -			/* Swap FC QoS or FCoE stats */ -			if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) { -				bfa_fcport_qos_stats_swap( -					&fcport->stats_ret->fcqos, -					&fcport->stats->fcqos); -			} else { -				bfa_fcport_fcoe_stats_swap( -					&fcport->stats_ret->fcoe, -					&fcport->stats->fcoe); - -				bfa_os_gettimeofday(&tv); -				fcport->stats_ret->fcoe.secs_reset = +		struct timeval tv; +		if (fcport->stats_status == BFA_STATUS_OK) +			do_gettimeofday(&tv); + +		list_for_each_safe(qe, qen, &fcport->stats_pending_q) { +			bfa_q_deq(&fcport->stats_pending_q, &qe); +			cb = (struct bfa_cb_pending_q_s *)qe; +			if (fcport->stats_status == BFA_STATUS_OK) { +				ret = (union bfa_fcport_stats_u *)cb->data; +				/* Swap FC QoS or FCoE stats */ +				if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) +					bfa_fcport_qos_stats_swap(&ret->fcqos, +							&fcport->stats->fcqos); +				else { +					bfa_fcport_fcoe_stats_swap(&ret->fcoe, +							&fcport->stats->fcoe); +					ret->fcoe.secs_reset =  					tv.tv_sec - fcport->stats_reset_time; +				}  			} +			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe, +					fcport->stats_status);  		} -		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); +		fcport->stats_status = BFA_STATUS_OK;  	} else { -		fcport->stats_busy = BFA_FALSE; +		INIT_LIST_HEAD(&fcport->stats_pending_q);  		fcport->stats_status = BFA_STATUS_OK;  	}  } @@ -3199,8 +3401,7 @@ bfa_fcport_stats_get_timeout(void *cbarg)  	}  	fcport->stats_status = BFA_STATUS_ETIMER; -	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get, -		fcport); +	__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);  }  static void @@ -3223,27 +3424,34 @@ bfa_fcport_send_stats_get(void *cbarg)  	memset(msg, 0, sizeof(struct bfi_fcport_req_s));  	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ, -			bfa_lpuid(fcport->bfa)); -	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT); +			bfa_fn_lpu(fcport->bfa)); +	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);  }  static void  __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)  { -	struct bfa_fcport_s *fcport = cbarg; +	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg; +	struct bfa_cb_pending_q_s *cb; +	struct list_head *qe, *qen;  	if (complete) { -		struct bfa_timeval_s tv; +		struct timeval tv;  		/*  		 * re-initialize time stamp for stats reset  		 */ -		bfa_os_gettimeofday(&tv); +		do_gettimeofday(&tv);  		fcport->stats_reset_time = tv.tv_sec; - -		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); +		list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) { +			bfa_q_deq(&fcport->statsclr_pending_q, &qe); +			cb = (struct bfa_cb_pending_q_s *)qe; +			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe, +						fcport->stats_status); +		} +		fcport->stats_status = BFA_STATUS_OK;  	} else { -		fcport->stats_busy = BFA_FALSE; +		INIT_LIST_HEAD(&fcport->statsclr_pending_q);  		fcport->stats_status = BFA_STATUS_OK;  	}  } @@ -3261,8 +3469,7 @@ bfa_fcport_stats_clr_timeout(void *cbarg)  	}  	fcport->stats_status = BFA_STATUS_ETIMER; -	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, -			__bfa_cb_fcport_stats_clr, fcport); +	__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);  }  static void @@ -3285,8 +3492,8 @@ bfa_fcport_send_stats_clear(void *cbarg)  	memset(msg, 0, sizeof(struct bfi_fcport_req_s));  	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ, -			bfa_lpuid(fcport->bfa)); -	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT); +			bfa_fn_lpu(fcport->bfa)); +	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);  }  /* @@ -3303,8 +3510,8 @@ bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)  	int link_bm = 0;  	bfa_trc(fcport->bfa, fcport->cfg.trunked); -	bfa_assert(scn->trunk_state == BFA_TRUNK_ONLINE || -		   scn->trunk_state == BFA_TRUNK_OFFLINE); +	WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE && +		   scn->trunk_state != BFA_TRUNK_OFFLINE);  	bfa_trc(fcport->bfa, trunk->attr.state);  	bfa_trc(fcport->bfa, scn->trunk_state); @@ -3396,12 +3603,6 @@ bfa_trunk_iocdisable(struct bfa_s *bfa)  	}  } - - -/* - *  hal_port_public - */ -  /*   * Called to initialize port attributes   */ @@ -3419,9 +3620,12 @@ bfa_fcport_init(struct bfa_s *bfa)  	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);  	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc); -	bfa_assert(fcport->cfg.maxfrsize); -	bfa_assert(fcport->cfg.rx_bbcredit); -	bfa_assert(fcport->speed_sup); +	if (bfa_fcport_is_pbcdisabled(bfa)) +		bfa->modules.port.pbc_disabled = BFA_TRUE; + +	WARN_ON(!fcport->cfg.maxfrsize); +	WARN_ON(!fcport->cfg.rx_bbcredit); +	WARN_ON(!fcport->speed_sup);  }  /* @@ -3441,8 +3645,44 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)  	switch (msg->mhdr.msg_id) {  	case BFI_FCPORT_I2H_ENABLE_RSP: -		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) +		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) { + +			fcport->stats_dma_ready = BFA_TRUE; +			if (fcport->use_flash_cfg) { +				fcport->cfg = i2hmsg.penable_rsp->port_cfg; +				fcport->cfg.maxfrsize = +					cpu_to_be16(fcport->cfg.maxfrsize); +				fcport->cfg.path_tov = +					cpu_to_be16(fcport->cfg.path_tov); +				fcport->cfg.q_depth = +					cpu_to_be16(fcport->cfg.q_depth); + +				if (fcport->cfg.trunked) +					fcport->trunk.attr.state = +						BFA_TRUNK_OFFLINE; +				else +					fcport->trunk.attr.state = +						BFA_TRUNK_DISABLED; +				fcport->qos_attr.qos_bw = +					i2hmsg.penable_rsp->port_cfg.qos_bw; +				fcport->use_flash_cfg = BFA_FALSE; +			} + +			if (fcport->cfg.qos_enabled) +				fcport->qos_attr.state = BFA_QOS_OFFLINE; +			else +				fcport->qos_attr.state = BFA_QOS_DISABLED; + +			fcport->qos_attr.qos_bw_op = +					i2hmsg.penable_rsp->port_cfg.qos_bw; + +			if (fcport->cfg.bb_cr_enabled) +				fcport->bbcr_attr.state = BFA_BBCR_OFFLINE; +			else +				fcport->bbcr_attr.state = BFA_BBCR_DISABLED; +  			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP); +		}  		break;  	case BFI_FCPORT_I2H_DISABLE_RSP: @@ -3451,10 +3691,24 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)  		break;  	case BFI_FCPORT_I2H_EVENT: +		if (fcport->cfg.bb_cr_enabled) +			fcport->bbcr_attr.state = BFA_BBCR_OFFLINE; +		else +			fcport->bbcr_attr.state = BFA_BBCR_DISABLED; +  		if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)  			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP); -		else -			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN); +		else { +			if (i2hmsg.event->link_state.linkstate_rsn == +			    BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG) +				bfa_sm_send_event(fcport, +						  BFA_FCPORT_SM_FAA_MISCONFIG); +			else +				bfa_sm_send_event(fcport, +						  BFA_FCPORT_SM_LINKDOWN); +		} +		fcport->qos_attr.qos_bw_op = +				i2hmsg.event->link_state.qos_attr.qos_bw_op;  		break;  	case BFI_FCPORT_I2H_TRUNK_SCN: @@ -3465,28 +3719,26 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)  		/*  		 * check for timer pop before processing the rsp  		 */ -		if (fcport->stats_busy == BFA_FALSE || -		    fcport->stats_status == BFA_STATUS_ETIMER) +		if (list_empty(&fcport->stats_pending_q) || +		    (fcport->stats_status == BFA_STATUS_ETIMER))  			break;  		bfa_timer_stop(&fcport->timer);  		fcport->stats_status = i2hmsg.pstatsget_rsp->status; -		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, -				__bfa_cb_fcport_stats_get, fcport); +		__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);  		break;  	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:  		/*  		 * check for timer pop before processing the rsp  		 */ -		if (fcport->stats_busy == BFA_FALSE || -		    fcport->stats_status == BFA_STATUS_ETIMER) +		if (list_empty(&fcport->statsclr_pending_q) || +		    (fcport->stats_status == BFA_STATUS_ETIMER))  			break;  		bfa_timer_stop(&fcport->timer);  		fcport->stats_status = BFA_STATUS_OK; -		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, -				__bfa_cb_fcport_stats_clr, fcport); +		__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);  		break;  	case BFI_FCPORT_I2H_ENABLE_AEN: @@ -3498,17 +3750,11 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)  		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  	break;  	}  } - - -/* - *  hal_port_api - */ -  /*   * Registered callback for port events.   */ @@ -3529,6 +3775,9 @@ bfa_fcport_enable(struct bfa_s *bfa)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); +	if (bfa_fcport_is_pbcdisabled(bfa)) +		return BFA_STATUS_PBC; +  	if (bfa_ioc_is_disabled(&bfa->ioc))  		return BFA_STATUS_IOC_DISABLED; @@ -3542,6 +3791,8 @@ bfa_fcport_enable(struct bfa_s *bfa)  bfa_status_t  bfa_fcport_disable(struct bfa_s *bfa)  { +	if (bfa_fcport_is_pbcdisabled(bfa)) +		return BFA_STATUS_PBC;  	if (bfa_ioc_is_disabled(&bfa->ioc))  		return BFA_STATUS_IOC_DISABLED; @@ -3550,6 +3801,21 @@ bfa_fcport_disable(struct bfa_s *bfa)  	return BFA_STATUS_OK;  } +/* If PBC is disabled on port, return error */ +bfa_status_t +bfa_fcport_is_pbcdisabled(struct bfa_s *bfa) +{ +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); +	struct bfa_iocfc_s *iocfc = &bfa->iocfc; +	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; + +	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) { +		bfa_trc(bfa, fcport->pwwn); +		return BFA_STATUS_PBC; +	} +	return BFA_STATUS_OK; +} +  /*   * Configure port speed.   */ @@ -3562,11 +3828,34 @@ bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)  	if (fcport->cfg.trunked == BFA_TRUE)  		return BFA_STATUS_TRUNK_ENABLED; +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) && +			(speed == BFA_PORT_SPEED_16GBPS)) +		return BFA_STATUS_UNSUPP_SPEED;  	if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {  		bfa_trc(bfa, fcport->speed_sup);  		return BFA_STATUS_UNSUPP_SPEED;  	} +	/* Port speed entered needs to be checked */ +	if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) { +		/* For CT2, 1G is not supported */ +		if ((speed == BFA_PORT_SPEED_1GBPS) && +		    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) +			return BFA_STATUS_UNSUPP_SPEED; + +		/* Already checked for Auto Speed and Max Speed supp */ +		if (!(speed == BFA_PORT_SPEED_1GBPS || +		      speed == BFA_PORT_SPEED_2GBPS || +		      speed == BFA_PORT_SPEED_4GBPS || +		      speed == BFA_PORT_SPEED_8GBPS || +		      speed == BFA_PORT_SPEED_16GBPS || +		      speed == BFA_PORT_SPEED_AUTO)) +			return BFA_STATUS_UNSUPP_SPEED; +	} else { +		if (speed != BFA_PORT_SPEED_10GBPS) +			return BFA_STATUS_UNSUPP_SPEED; +	} +  	fcport->cfg.speed = speed;  	return BFA_STATUS_OK; @@ -3596,7 +3885,28 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)  	switch (topology) {  	case BFA_PORT_TOPOLOGY_P2P: +		break; +  	case BFA_PORT_TOPOLOGY_LOOP: +		if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) || +			(fcport->qos_attr.state != BFA_QOS_DISABLED)) +			return BFA_STATUS_ERROR_QOS_ENABLED; +		if (fcport->cfg.ratelimit != BFA_FALSE) +			return BFA_STATUS_ERROR_TRL_ENABLED; +		if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) || +			(fcport->trunk.attr.state != BFA_TRUNK_DISABLED)) +			return BFA_STATUS_ERROR_TRUNK_ENABLED; +		if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) || +			(fcport->cfg.speed == BFA_PORT_SPEED_16GBPS)) +			return BFA_STATUS_UNSUPP_SPEED; +		if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) +			return BFA_STATUS_LOOP_UNSUPP_MEZZ; +		if (bfa_fcport_is_dport(bfa) != BFA_FALSE) +			return BFA_STATUS_DPORT_ERR; +		if (bfa_fcport_is_ddport(bfa) != BFA_FALSE) +			return BFA_STATUS_DPORT_ERR; +		break; +  	case BFA_PORT_TOPOLOGY_AUTO:  		break; @@ -3619,6 +3929,17 @@ bfa_fcport_get_topology(struct bfa_s *bfa)  	return fcport->topology;  } +/** + * Get config topology. + */ +enum bfa_port_topology +bfa_fcport_get_cfg_topology(struct bfa_s *bfa) +{ +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); + +	return fcport->cfg.topology; +} +  bfa_status_t  bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)  { @@ -3694,9 +4015,11 @@ bfa_fcport_get_maxfrsize(struct bfa_s *bfa)  u8  bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)  { -	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); +	if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) +		return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit; -	return fcport->cfg.rx_bbcredit; +	else +		return 0;  }  void @@ -3705,7 +4028,6 @@ bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);  	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit; -	bfa_fcport_send_txcredit(fcport);  }  /* @@ -3732,8 +4054,8 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)  	attr->nwwn = fcport->nwwn;  	attr->pwwn = fcport->pwwn; -	attr->factorypwwn =  bfa_ioc_get_mfg_pwwn(&bfa->ioc); -	attr->factorynwwn =  bfa_ioc_get_mfg_nwwn(&bfa->ioc); +	attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn; +	attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;  	memcpy(&attr->pport_cfg, &fcport->cfg,  		sizeof(struct bfa_port_cfg_s)); @@ -3751,16 +4073,22 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)  	/* beacon attributes */  	attr->beacon = fcport->beacon;  	attr->link_e2e_beacon = fcport->link_e2e_beacon; -	attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog); -	attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);  	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);  	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);  	attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm); -	if (bfa_ioc_is_disabled(&fcport->bfa->ioc)) -		attr->port_state = BFA_PORT_ST_IOCDIS; -	else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc)) -		attr->port_state = BFA_PORT_ST_FWMISMATCH; + +	attr->fec_state = fcport->fec_state; + +	/* PBC Disabled State */ +	if (bfa_fcport_is_pbcdisabled(bfa)) +		attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED; +	else { +		if (bfa_ioc_is_disabled(&fcport->bfa->ioc)) +			attr->port_state = BFA_PORT_ST_IOCDIS; +		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc)) +			attr->port_state = BFA_PORT_ST_FWMISMATCH; +	}  	/* FCoE vlan */  	attr->fcoe_vlan = fcport->fcoe_vlan; @@ -3772,25 +4100,26 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)   * Fetch port statistics (FCQoS or FCoE).   */  bfa_status_t -bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, -	bfa_cb_port_t cbfn, void *cbarg) +bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	if (fcport->stats_busy) { -		bfa_trc(bfa, fcport->stats_busy); -		return BFA_STATUS_DEVBUSY; -	} +	if (!bfa_iocfc_is_operational(bfa) || +	    !fcport->stats_dma_ready) +		return BFA_STATUS_IOC_NON_OP; -	fcport->stats_busy  = BFA_TRUE; -	fcport->stats_ret   = stats; -	fcport->stats_cbfn  = cbfn; -	fcport->stats_cbarg = cbarg; +	if (!list_empty(&fcport->statsclr_pending_q)) +		return BFA_STATUS_DEVBUSY; -	bfa_fcport_send_stats_get(fcport); +	if (list_empty(&fcport->stats_pending_q)) { +		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q); +		bfa_fcport_send_stats_get(fcport); +		bfa_timer_start(bfa, &fcport->timer, +				bfa_fcport_stats_get_timeout, +				fcport, BFA_FCPORT_STATS_TOV); +	} else +		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q); -	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout, -			fcport, BFA_FCPORT_STATS_TOV);  	return BFA_STATUS_OK;  } @@ -3798,111 +4127,30 @@ bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,   * Reset port statistics (FCQoS or FCoE).   */  bfa_status_t -bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) +bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	if (fcport->stats_busy) { -		bfa_trc(bfa, fcport->stats_busy); -		return BFA_STATUS_DEVBUSY; -	} +	if (!bfa_iocfc_is_operational(bfa) || +	    !fcport->stats_dma_ready) +		return BFA_STATUS_IOC_NON_OP; -	fcport->stats_busy  = BFA_TRUE; -	fcport->stats_cbfn  = cbfn; -	fcport->stats_cbarg = cbarg; +	if (!list_empty(&fcport->stats_pending_q)) +		return BFA_STATUS_DEVBUSY; -	bfa_fcport_send_stats_clear(fcport); +	if (list_empty(&fcport->statsclr_pending_q)) { +		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q); +		bfa_fcport_send_stats_clear(fcport); +		bfa_timer_start(bfa, &fcport->timer, +				bfa_fcport_stats_clr_timeout, +				fcport, BFA_FCPORT_STATS_TOV); +	} else +		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q); -	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout, -			fcport, BFA_FCPORT_STATS_TOV);  	return BFA_STATUS_OK;  }  /* - * Fetch FCQoS port statistics - */ -bfa_status_t -bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, -	bfa_cb_port_t cbfn, void *cbarg) -{ -	/* Meaningful only for FC mode */ -	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc)); - -	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg); -} - -/* - * Reset FCoE port statistics - */ -bfa_status_t -bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) -{ -	/* Meaningful only for FC mode */ -	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc)); - -	return bfa_fcport_clear_stats(bfa, cbfn, cbarg); -} - -/* - * Fetch FCQoS port statistics - */ -bfa_status_t -bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, -	bfa_cb_port_t cbfn, void *cbarg) -{ -	/* Meaningful only for FCoE mode */ -	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc)); - -	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg); -} - -/* - * Reset FCoE port statistics - */ -bfa_status_t -bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) -{ -	/* Meaningful only for FCoE mode */ -	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc)); - -	return bfa_fcport_clear_stats(bfa, cbfn, cbarg); -} - -void -bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr) -{ -	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - -	qos_attr->state = fcport->qos_attr.state; -	qos_attr->total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr); -} - -void -bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa, -	struct bfa_qos_vc_attr_s *qos_vc_attr) -{ -	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr; -	u32 i = 0; - -	qos_vc_attr->total_vc_count = be16_to_cpu(bfa_vc_attr->total_vc_count); -	qos_vc_attr->shared_credit  = be16_to_cpu(bfa_vc_attr->shared_credit); -	qos_vc_attr->elp_opmode_flags  = -			be32_to_cpu(bfa_vc_attr->elp_opmode_flags); - -	/* Individual VC info */ -	while (i < qos_vc_attr->total_vc_count) { -		qos_vc_attr->vc_info[i].vc_credit	= -				bfa_vc_attr->vc_info[i].vc_credit; -		qos_vc_attr->vc_info[i].borrow_credit	= -				bfa_vc_attr->vc_info[i].borrow_credit; -		qos_vc_attr->vc_info[i].priority	= -				bfa_vc_attr->vc_info[i].priority; -		++i; -	} -} - -/*   * Fetch port attributes.   */  bfa_boolean_t @@ -3916,66 +4164,67 @@ bfa_fcport_is_disabled(struct bfa_s *bfa)  }  bfa_boolean_t -bfa_fcport_is_ratelim(struct bfa_s *bfa) +bfa_fcport_is_dport(struct bfa_s *bfa)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE; +	return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) == +		BFA_PORT_ST_DPORT); +} + +bfa_boolean_t +bfa_fcport_is_ddport(struct bfa_s *bfa) +{ +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); +	return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) == +		BFA_PORT_ST_DDPORT);  } -void -bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off) +bfa_status_t +bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);  	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa); -	bfa_trc(bfa, on_off); -	bfa_trc(bfa, fcport->cfg.qos_enabled); -  	bfa_trc(bfa, ioc_type); -	if (ioc_type == BFA_IOC_TYPE_FC) { -		fcport->cfg.qos_enabled = on_off; -		/* -		 * Notify fcpim of the change in QoS state -		 */ -		bfa_fcpim_update_ioredirect(bfa); -	} +	if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0)) +		return BFA_STATUS_QOS_BW_INVALID; + +	if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100) +		return BFA_STATUS_QOS_BW_INVALID; + +	if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) || +	    (qos_bw->low > qos_bw->high)) +		return BFA_STATUS_QOS_BW_INVALID; + +	if ((ioc_type == BFA_IOC_TYPE_FC) && +	    (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP)) +		fcport->cfg.qos_bw = *qos_bw; + +	return BFA_STATUS_OK;  } -void -bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off) +bfa_boolean_t +bfa_fcport_is_ratelim(struct bfa_s *bfa)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	bfa_trc(bfa, on_off); -	bfa_trc(bfa, fcport->cfg.ratelimit); +	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE; -	fcport->cfg.ratelimit = on_off; -	if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN) -		fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;  }  /* - * Configure default minimum ratelim speed + *	Enable/Disable FAA feature in port config   */ -bfa_status_t -bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_port_speed speed) +void +bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	bfa_trc(bfa, speed); - -	/* Auto and speeds greater than the supported speed, are invalid */ -	if ((speed == BFA_PORT_SPEED_AUTO) || (speed > fcport->speed_sup)) { -		bfa_trc(bfa, fcport->speed_sup); -		return BFA_STATUS_UNSUPP_SPEED; -	} - -	fcport->cfg.trl_def_speed = speed; - -	return BFA_STATUS_OK; +	bfa_trc(bfa, state); +	fcport->cfg.faa_state = state;  }  /* @@ -3990,20 +4239,10 @@ bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)  	return fcport->cfg.trl_def_speed;  } -void -bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status) -{ -	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - -	bfa_trc(bfa, status); -	bfa_trc(bfa, fcport->diag_busy); - -	fcport->diag_busy = status; -}  void  bfa_fcport_beacon(void *dev, bfa_boolean_t beacon, -	bfa_boolean_t link_e2e_beacon) +		  bfa_boolean_t link_e2e_beacon)  {  	struct bfa_s *bfa = dev;  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); @@ -4036,62 +4275,122 @@ bfa_fcport_is_qos_enabled(struct bfa_s *bfa)  	return fcport->cfg.qos_enabled;  } -bfa_status_t -bfa_trunk_get_attr(struct bfa_s *bfa, struct bfa_trunk_attr_s *attr) - +bfa_boolean_t +bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	struct bfa_fcport_trunk_s *trunk = &fcport->trunk; -	bfa_trc(bfa, fcport->cfg.trunked); -	bfa_trc(bfa, trunk->attr.state); -	*attr = trunk->attr; -	attr->port_id = bfa_lps_get_base_pid(bfa); - -	return BFA_STATUS_OK; +	return fcport->cfg.trunked;  } -void -bfa_trunk_enable_cfg(struct bfa_s *bfa) +bfa_status_t +bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	struct bfa_fcport_trunk_s *trunk = &fcport->trunk; -	bfa_trc(bfa, 1); -	trunk->attr.state = BFA_TRUNK_OFFLINE; -	fcport->cfg.trunked = BFA_TRUE; +	bfa_trc(bfa, on_off); + +	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC) +		return BFA_STATUS_BBCR_FC_ONLY; + +	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) && +		(bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK)) +		return BFA_STATUS_CMD_NOTSUPP_MEZZ; + +	if (on_off) { +		if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) +			return BFA_STATUS_TOPOLOGY_LOOP; + +		if (fcport->cfg.qos_enabled) +			return BFA_STATUS_ERROR_QOS_ENABLED; + +		if (fcport->cfg.trunked) +			return BFA_STATUS_TRUNK_ENABLED; + +		if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) && +			(fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc))) +			return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT; + +		if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS) +			return BFA_STATUS_FEATURE_NOT_SUPPORTED; + +		if (fcport->cfg.bb_cr_enabled) { +			if (bb_scn != fcport->cfg.bb_scn) +				return BFA_STATUS_BBCR_CFG_NO_CHANGE; +			else +				return BFA_STATUS_NO_CHANGE; +		} + +		if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX)) +			bb_scn = BFA_BB_SCN_DEF; + +		fcport->cfg.bb_cr_enabled = on_off; +		fcport->cfg.bb_scn = bb_scn; +	} else { +		if (!fcport->cfg.bb_cr_enabled) +			return BFA_STATUS_NO_CHANGE; + +		fcport->cfg.bb_cr_enabled = on_off; +		fcport->cfg.bb_scn = 0; +	} + +	return BFA_STATUS_OK;  }  bfa_status_t -bfa_trunk_enable(struct bfa_s *bfa) +bfa_fcport_get_bbcr_attr(struct bfa_s *bfa, +		struct bfa_bbcr_attr_s *bbcr_attr)  {  	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	struct bfa_fcport_trunk_s *trunk = &fcport->trunk; -	bfa_trc(bfa, 1); +	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC) +		return BFA_STATUS_BBCR_FC_ONLY; -	trunk->attr.state   = BFA_TRUNK_OFFLINE; -	bfa_fcport_disable(bfa); -	fcport->cfg.trunked = BFA_TRUE; -	bfa_fcport_enable(bfa); +	if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) +		return BFA_STATUS_TOPOLOGY_LOOP; + +	*bbcr_attr = fcport->bbcr_attr;  	return BFA_STATUS_OK;  } -bfa_status_t -bfa_trunk_disable(struct bfa_s *bfa) +void +bfa_fcport_dportenable(struct bfa_s *bfa)  { -	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); -	struct bfa_fcport_trunk_s *trunk = &fcport->trunk; +	/* +	 * Assume caller check for port is in disable state +	 */ +	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE); +	bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE); +} -	bfa_trc(bfa, 0); -	trunk->attr.state   = BFA_TRUNK_DISABLED; -	bfa_fcport_disable(bfa); -	fcport->cfg.trunked = BFA_FALSE; -	bfa_fcport_enable(bfa); -	return BFA_STATUS_OK; +void +bfa_fcport_dportdisable(struct bfa_s *bfa) +{ +	/* +	 * Assume caller check for port is in disable state +	 */ +	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE); +	bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);  } +void +bfa_fcport_ddportenable(struct bfa_s *bfa) +{ +	/* +	 * Assume caller check for port is in disable state +	 */ +	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE); +} + +void +bfa_fcport_ddportdisable(struct bfa_s *bfa) +{ +	/* +	 * Assume caller check for port is in disable state +	 */ +	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE); +}  /*   * Rport State machine functions @@ -4387,6 +4686,10 @@ bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)  		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);  		break; +	case BFA_RPORT_SM_OFFLINE: +		bfa_rport_offline_cb(rp); +		break; +  	default:  		bfa_stats(rp, sm_off_unexp);  		bfa_sm_fault(rp->bfa, event); @@ -4503,6 +4806,7 @@ bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,  	case BFA_RPORT_SM_HWFAIL:  		bfa_stats(rp, sm_offp_hwf);  		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); +		bfa_rport_offline_cb(rp);  		break;  	default: @@ -4582,18 +4886,22 @@ bfa_rport_qresume(void *cbarg)  }  static void -bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -		u32 *dm_len) +bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo, +		struct bfa_s *bfa)  { +	struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa); +  	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)  		cfg->fwcfg.num_rports = BFA_RPORT_MIN; -	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s); +	/* kva memory */ +	bfa_mem_kva_setup(minfo, rport_kva, +		cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));  }  static void  bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) +		struct bfa_pcidev_s *pcidev)  {  	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);  	struct bfa_rport_s *rp; @@ -4601,13 +4909,14 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	INIT_LIST_HEAD(&mod->rp_free_q);  	INIT_LIST_HEAD(&mod->rp_active_q); +	INIT_LIST_HEAD(&mod->rp_unused_q); -	rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo); +	rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);  	mod->rps_list = rp;  	mod->num_rports = cfg->fwcfg.num_rports; -	bfa_assert(mod->num_rports && -		   !(mod->num_rports & (mod->num_rports - 1))); +	WARN_ON(!mod->num_rports || +		   (mod->num_rports & (mod->num_rports - 1)));  	for (i = 0; i < mod->num_rports; i++, rp++) {  		memset(rp, 0, sizeof(struct bfa_rport_s)); @@ -4627,7 +4936,7 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	/*  	 * consume memory  	 */ -	bfa_meminfo_kva(meminfo) = (u8 *) rp; +	bfa_mem_kva_curp(mod) = (u8 *) rp;  }  static void @@ -4652,6 +4961,9 @@ bfa_rport_iocdisable(struct bfa_s *bfa)  	struct bfa_rport_s *rport;  	struct list_head *qe, *qen; +	/* Enqueue unused rport resources to free_q */ +	list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q); +  	list_for_each_safe(qe, qen, &mod->rp_active_q) {  		rport = (struct bfa_rport_s *) qe;  		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL); @@ -4675,7 +4987,7 @@ bfa_rport_free(struct bfa_rport_s *rport)  {  	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa); -	bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport)); +	WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));  	list_del(&rport->qe);  	list_add_tail(&rport->qe, &mod->rp_free_q);  } @@ -4695,11 +5007,11 @@ bfa_rport_send_fwcreate(struct bfa_rport_s *rp)  	}  	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ, -			bfa_lpuid(rp->bfa)); +			bfa_fn_lpu(rp->bfa));  	m->bfa_handle = rp->rport_tag;  	m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);  	m->pid = rp->rport_info.pid; -	m->lp_tag = rp->rport_info.lp_tag; +	m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);  	m->local_pid = rp->rport_info.local_pid;  	m->fc_class = rp->rport_info.fc_class;  	m->vf_en = rp->rport_info.vf_en; @@ -4709,7 +5021,7 @@ bfa_rport_send_fwcreate(struct bfa_rport_s *rp)  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT); +	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);  	return BFA_TRUE;  } @@ -4728,13 +5040,13 @@ bfa_rport_send_fwdelete(struct bfa_rport_s *rp)  	}  	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ, -			bfa_lpuid(rp->bfa)); +			bfa_fn_lpu(rp->bfa));  	m->fw_handle = rp->fw_handle;  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT); +	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);  	return BFA_TRUE;  } @@ -4753,14 +5065,14 @@ bfa_rport_send_fwspeed(struct bfa_rport_s *rp)  	}  	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ, -			bfa_lpuid(rp->bfa)); +			bfa_fn_lpu(rp->bfa));  	m->fw_handle = rp->fw_handle;  	m->speed = (u8)rp->rport_info.speed;  	/*  	 * queue I/O message to firmware  	 */ -	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT); +	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);  	return BFA_TRUE;  } @@ -4788,13 +5100,15 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);  		rp->fw_handle = msg.create_rsp->fw_handle;  		rp->qos_attr = msg.create_rsp->qos_attr; -		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK); +		bfa_rport_set_lunmask(bfa, rp); +		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);  		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);  		break;  	case BFI_RPORT_I2H_DELETE_RSP:  		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle); -		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK); +		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK); +		bfa_rport_unset_lunmask(bfa, rp);  		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);  		break; @@ -4804,13 +5118,39 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)  		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);  		break; +	case BFI_RPORT_I2H_LIP_SCN_ONLINE: +		bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa), +				&msg.lip_scn->loop_info); +		bfa_cb_rport_scn_online(bfa); +		break; + +	case BFI_RPORT_I2H_LIP_SCN_OFFLINE: +		bfa_cb_rport_scn_offline(bfa); +		break; + +	case BFI_RPORT_I2H_NO_DEV: +		rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle); +		bfa_cb_rport_scn_no_dev(rp->rport_drv); +		break; +  	default:  		bfa_trc(bfa, m->mhdr.msg_id); -		bfa_assert(0); +		WARN_ON(1);  	}  } +void +bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw) +{ +	struct bfa_rport_mod_s	*mod = BFA_RPORT_MOD(bfa); +	struct list_head	*qe; +	int	i; +	for (i = 0; i < (mod->num_rports - num_rport_fw); i++) { +		bfa_q_deq_tail(&mod->rp_free_q, &qe); +		list_add_tail(qe, &mod->rp_unused_q); +	} +}  /*   *  bfa_rport_api @@ -4828,24 +5168,18 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv)  	rp->bfa = bfa;  	rp->rport_drv = rport_drv; -	bfa_rport_clear_stats(rp); +	memset(&rp->stats, 0, sizeof(rp->stats)); -	bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit)); +	WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));  	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);  	return rp;  }  void -bfa_rport_delete(struct bfa_rport_s *rport) -{ -	bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE); -} - -void  bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)  { -	bfa_assert(rport_info->max_frmsz != 0); +	WARN_ON(rport_info->max_frmsz == 0);  	/*  	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI @@ -4861,43 +5195,48 @@ bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)  }  void -bfa_rport_offline(struct bfa_rport_s *rport) -{ -	bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE); -} - -void  bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)  { -	bfa_assert(speed != 0); -	bfa_assert(speed != BFA_PORT_SPEED_AUTO); +	WARN_ON(speed == 0); +	WARN_ON(speed == BFA_PORT_SPEED_AUTO); -	rport->rport_info.speed = speed; -	bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); +	if (rport) { +		rport->rport_info.speed = speed; +		bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); +	}  } +/* Set Rport LUN Mask */  void -bfa_rport_get_stats(struct bfa_rport_s *rport, -	struct bfa_rport_hal_stats_s *stats) +bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)  { -	*stats = rport->stats; -} +	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa); +	wwn_t	lp_wwn, rp_wwn; +	u8 lp_tag = (u8)rp->rport_info.lp_tag; -void -bfa_rport_get_qos_attr(struct bfa_rport_s *rport, -					struct bfa_rport_qos_attr_s *qos_attr) -{ -	qos_attr->qos_priority  = rport->qos_attr.qos_priority; -	qos_attr->qos_flow_id  = be32_to_cpu(rport->qos_attr.qos_flow_id); +	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn; +	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn; +	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask = +					rp->lun_mask = BFA_TRUE; +	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);  } +/* Unset Rport LUN mask */  void -bfa_rport_clear_stats(struct bfa_rport_s *rport) +bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)  { -	memset(&rport->stats, 0, sizeof(rport->stats)); -} +	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa); +	wwn_t	lp_wwn, rp_wwn; +	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn; +	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn; + +	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask = +				rp->lun_mask = BFA_FALSE; +	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, +			BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID); +}  /*   * SGPG related functions @@ -4907,26 +5246,51 @@ bfa_rport_clear_stats(struct bfa_rport_s *rport)   * Compute and return memory needed by FCP(im) module.   */  static void -bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, -		u32 *dm_len) +bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo, +		struct bfa_s *bfa)  { +	struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa); +	struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa); +	struct bfa_mem_dma_s *seg_ptr; +	u16	nsegs, idx, per_seg_sgpg, num_sgpg; +	u32	sgpg_sz = sizeof(struct bfi_sgpg_s); +  	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)  		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN; +	else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX) +		cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX; + +	num_sgpg = cfg->drvcfg.num_sgpgs; + +	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz); +	per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz); + +	bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) { +		if (num_sgpg >= per_seg_sgpg) { +			num_sgpg -= per_seg_sgpg; +			bfa_mem_dma_setup(minfo, seg_ptr, +					per_seg_sgpg * sgpg_sz); +		} else +			bfa_mem_dma_setup(minfo, seg_ptr, +					num_sgpg * sgpg_sz); +	} -	*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s); -	*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s); +	/* kva memory */ +	bfa_mem_kva_setup(minfo, sgpg_kva, +		cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));  } -  static void  bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -		    struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev) +		struct bfa_pcidev_s *pcidev)  {  	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); -	int i;  	struct bfa_sgpg_s *hsgpg;  	struct bfi_sgpg_s *sgpg;  	u64 align_len; +	struct bfa_mem_dma_s *seg_ptr; +	u32	sgpg_sz = sizeof(struct bfi_sgpg_s); +	u16	i, idx, nsegs, per_seg_sgpg, num_sgpg;  	union {  		u64 pa; @@ -4938,39 +5302,45 @@ bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,  	bfa_trc(bfa, cfg->drvcfg.num_sgpgs); -	mod->num_sgpgs = cfg->drvcfg.num_sgpgs; -	mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo); -	align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa); -	mod->sgpg_arr_pa += align_len; -	mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) + -						align_len); -	mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) + -						align_len); +	mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs; + +	num_sgpg = cfg->drvcfg.num_sgpgs; +	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz); + +	/* dma/kva mem claim */ +	hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod); + +	bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) { + +		if (!bfa_mem_dma_virt(seg_ptr)) +			break; + +		align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) - +					     bfa_mem_dma_phys(seg_ptr); -	hsgpg = mod->hsgpg_arr; -	sgpg = mod->sgpg_arr; -	sgpg_pa.pa = mod->sgpg_arr_pa; -	mod->free_sgpgs = mod->num_sgpgs; +		sgpg = (struct bfi_sgpg_s *) +			(((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len); +		sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len; +		WARN_ON(sgpg_pa.pa & (sgpg_sz - 1)); -	bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1))); +		per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz; -	for (i = 0; i < mod->num_sgpgs; i++) { -		memset(hsgpg, 0, sizeof(*hsgpg)); -		memset(sgpg, 0, sizeof(*sgpg)); +		for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) { +			memset(hsgpg, 0, sizeof(*hsgpg)); +			memset(sgpg, 0, sizeof(*sgpg)); -		hsgpg->sgpg = sgpg; -		sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa); -		hsgpg->sgpg_pa = sgpg_pa_tmp.addr; -		list_add_tail(&hsgpg->qe, &mod->sgpg_q); +			hsgpg->sgpg = sgpg; +			sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa); +			hsgpg->sgpg_pa = sgpg_pa_tmp.addr; +			list_add_tail(&hsgpg->qe, &mod->sgpg_q); -		hsgpg++; -		sgpg++; -		sgpg_pa.pa += sizeof(struct bfi_sgpg_s); +			sgpg++; +			hsgpg++; +			sgpg_pa.pa += sgpg_sz; +		}  	} -	bfa_meminfo_kva(minfo) = (u8 *) hsgpg; -	bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg; -	bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa; +	bfa_mem_kva_curp(mod) = (u8 *) hsgpg;  }  static void @@ -4993,12 +5363,6 @@ bfa_sgpg_iocdisable(struct bfa_s *bfa)  {  } - - -/* - *  hal_sgpg_public BFA SGPG public functions - */ -  bfa_status_t  bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)  { @@ -5006,14 +5370,12 @@ bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)  	struct bfa_sgpg_s *hsgpg;  	int i; -	bfa_trc_fp(bfa, nsgpgs); -  	if (mod->free_sgpgs < nsgpgs)  		return BFA_STATUS_ENOMEM;  	for (i = 0; i < nsgpgs; i++) {  		bfa_q_deq(&mod->sgpg_q, &hsgpg); -		bfa_assert(hsgpg); +		WARN_ON(!hsgpg);  		list_add_tail(&hsgpg->qe, sgpg_q);  	} @@ -5027,10 +5389,8 @@ bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)  	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);  	struct bfa_sgpg_wqe_s *wqe; -	bfa_trc_fp(bfa, nsgpg); -  	mod->free_sgpgs += nsgpg; -	bfa_assert(mod->free_sgpgs <= mod->num_sgpgs); +	WARN_ON(mod->free_sgpgs > mod->num_sgpgs);  	list_splice_tail_init(sgpg_q, &mod->sgpg_q); @@ -5060,8 +5420,8 @@ bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)  {  	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); -	bfa_assert(nsgpg > 0); -	bfa_assert(nsgpg > mod->free_sgpgs); +	WARN_ON(nsgpg <= 0); +	WARN_ON(nsgpg <= mod->free_sgpgs);  	wqe->nsgpg_total = wqe->nsgpg = nsgpg; @@ -5072,7 +5432,7 @@ bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)  		/*  		 * no one else is waiting for SGPG  		 */ -		bfa_assert(list_empty(&mod->sgpg_wait_q)); +		WARN_ON(!list_empty(&mod->sgpg_wait_q));  		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);  		wqe->nsgpg -= mod->free_sgpgs;  		mod->free_sgpgs = 0; @@ -5086,7 +5446,7 @@ bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)  {  	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); -	bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe)); +	WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));  	list_del(&wqe->qe);  	if (wqe->nsgpg_total != wqe->nsgpg) @@ -5122,31 +5482,13 @@ __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)  }  static void -claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) -{ -	u32 uf_pb_tot_sz; - -	ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi); -	ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi); -	uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs), -							BFA_DMA_ALIGN_SZ); - -	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz; -	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz; - -	memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz); -} - -static void -claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) +claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)  {  	struct bfi_uf_buf_post_s *uf_bp_msg; -	struct bfi_sge_s      *sge; -	union bfi_addr_u      sga_zero = { {0} };  	u16 i;  	u16 buf_len; -	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi); +	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);  	uf_bp_msg = ufm->uf_buf_posts;  	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs; @@ -5157,28 +5499,18 @@ claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)  		buf_len = sizeof(struct bfa_uf_buf_s);  		uf_bp_msg->buf_len = cpu_to_be16(buf_len);  		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST, -			    bfa_lpuid(ufm->bfa)); - -		sge = uf_bp_msg->sge; -		sge[0].sg_len = buf_len; -		sge[0].flags = BFI_SGE_DATA_LAST; -		bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i)); -		bfa_sge_to_be(sge); - -		sge[1].sg_len = buf_len; -		sge[1].flags = BFI_SGE_PGDLEN; -		sge[1].sga = sga_zero; -		bfa_sge_to_be(&sge[1]); +			    bfa_fn_lpu(ufm->bfa)); +		bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));  	}  	/*  	 * advance pointer beyond consumed memory  	 */ -	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg; +	bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;  }  static void -claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) +claim_ufs(struct bfa_uf_mod_s *ufm)  {  	u16 i;  	struct bfa_uf_s   *uf; @@ -5186,7 +5518,7 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)  	/*  	 * Claim block of memory for UF list  	 */ -	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi); +	ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);  	/*  	 * Initialize UFs and queue it in UF free queue @@ -5195,8 +5527,8 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)  		memset(uf, 0, sizeof(struct bfa_uf_s));  		uf->bfa = ufm->bfa;  		uf->uf_tag = i; -		uf->pb_len = sizeof(struct bfa_uf_buf_s); -		uf->buf_kva = (void *)&ufm->uf_pbs_kva[i]; +		uf->pb_len = BFA_PER_UF_DMA_SZ; +		uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);  		uf->buf_pa = ufm_pbs_pa(ufm, i);  		list_add_tail(&uf->qe, &ufm->uf_free_q);  	} @@ -5204,48 +5536,57 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)  	/*  	 * advance memory pointer  	 */ -	bfa_meminfo_kva(mi) = (u8 *) uf; +	bfa_mem_kva_curp(ufm) = (u8 *) uf;  }  static void -uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) +uf_mem_claim(struct bfa_uf_mod_s *ufm)  { -	claim_uf_pbs(ufm, mi); -	claim_ufs(ufm, mi); -	claim_uf_post_msgs(ufm, mi); +	claim_ufs(ufm); +	claim_uf_post_msgs(ufm);  }  static void -bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len) +bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo, +		struct bfa_s *bfa)  { -	u32 num_ufs = cfg->fwcfg.num_uf_bufs; - -	/* -	 * dma-able memory for UF posted bufs -	 */ -	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs), -							BFA_DMA_ALIGN_SZ); +	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa); +	struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa); +	u32	num_ufs = cfg->fwcfg.num_uf_bufs; +	struct bfa_mem_dma_s *seg_ptr; +	u16	nsegs, idx, per_seg_uf = 0; + +	nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ); +	per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ); + +	bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) { +		if (num_ufs >= per_seg_uf) { +			num_ufs -= per_seg_uf; +			bfa_mem_dma_setup(minfo, seg_ptr, +				per_seg_uf * BFA_PER_UF_DMA_SZ); +		} else +			bfa_mem_dma_setup(minfo, seg_ptr, +				num_ufs * BFA_PER_UF_DMA_SZ); +	} -	/* -	 * kernel Virtual memory for UFs and UF buf post msg copies -	 */ -	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs; -	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs; +	/* kva memory */ +	bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs * +		(sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));  }  static void  bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, -		  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) +		struct bfa_pcidev_s *pcidev)  {  	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa); -	memset(ufm, 0, sizeof(struct bfa_uf_mod_s));  	ufm->bfa = bfa;  	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;  	INIT_LIST_HEAD(&ufm->uf_free_q);  	INIT_LIST_HEAD(&ufm->uf_posted_q); +	INIT_LIST_HEAD(&ufm->uf_unused_q); -	uf_mem_claim(ufm, meminfo); +	uf_mem_claim(ufm);  }  static void @@ -5279,7 +5620,7 @@ bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)  	memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],  		      sizeof(struct bfi_uf_buf_post_s)); -	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP); +	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);  	bfa_trc(ufm->bfa, uf->uf_tag); @@ -5303,11 +5644,15 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)  {  	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);  	u16 uf_tag = m->buf_tag; -	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];  	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag]; -	u8 *buf = &uf_buf->d[0]; +	struct bfa_uf_buf_s *uf_buf; +	uint8_t *buf;  	struct fchs_s *fchs; +	uf_buf = (struct bfa_uf_buf_s *) +			bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len); +	buf = &uf_buf->d[0]; +  	m->frm_len = be16_to_cpu(m->frm_len);  	m->xfr_len = be16_to_cpu(m->xfr_len); @@ -5318,7 +5663,7 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)  	uf->data_ptr = buf;  	uf->data_len = m->xfr_len; -	bfa_assert(uf->data_len >= sizeof(struct fchs_s)); +	WARN_ON(uf->data_len < sizeof(struct fchs_s));  	if (uf->data_len == sizeof(struct fchs_s)) {  		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX, @@ -5348,6 +5693,9 @@ bfa_uf_iocdisable(struct bfa_s *bfa)  	struct bfa_uf_s *uf;  	struct list_head *qe, *qen; +	/* Enqueue unused uf resources to free_q */ +	list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q); +  	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {  		uf = (struct bfa_uf_s *) qe;  		list_del(&uf->qe); @@ -5361,14 +5709,8 @@ bfa_uf_start(struct bfa_s *bfa)  	bfa_uf_post_all(BFA_UF_MOD(bfa));  } - -  /* - *  hal_uf_api - */ - -/* - * Register handler for all unsolicted recieve frames. + * Register handler for all unsolicted receive frames.   *   * @param[in]	bfa		BFA instance   * @param[in]	ufrecv	receive handler function @@ -5414,8 +5756,1307 @@ bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)  	default:  		bfa_trc(bfa, msg->mhdr.msg_id); -		bfa_assert(0); +		WARN_ON(1); +	} +} + +void +bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw) +{ +	struct bfa_uf_mod_s	*mod = BFA_UF_MOD(bfa); +	struct list_head	*qe; +	int	i; + +	for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) { +		bfa_q_deq_tail(&mod->uf_free_q, &qe); +		list_add_tail(qe, &mod->uf_unused_q); +	} +} + +/* + *	Dport forward declaration + */ + +enum bfa_dport_test_state_e { +	BFA_DPORT_ST_DISABLED	= 0,	/*!< dport is disabled */ +	BFA_DPORT_ST_INP	= 1,	/*!< test in progress */ +	BFA_DPORT_ST_COMP	= 2,	/*!< test complete successfully */ +	BFA_DPORT_ST_NO_SFP	= 3,	/*!< sfp is not present */ +	BFA_DPORT_ST_NOTSTART	= 4,	/*!< test not start dport is enabled */ +}; + +/* + * BFA DPORT state machine events + */ +enum bfa_dport_sm_event { +	BFA_DPORT_SM_ENABLE	= 1,	/* dport enable event         */ +	BFA_DPORT_SM_DISABLE    = 2,    /* dport disable event        */ +	BFA_DPORT_SM_FWRSP      = 3,    /* fw enable/disable rsp      */ +	BFA_DPORT_SM_QRESUME    = 4,    /* CQ space available         */ +	BFA_DPORT_SM_HWFAIL     = 5,    /* IOC h/w failure            */ +	BFA_DPORT_SM_START	= 6,	/* re-start dport test        */ +	BFA_DPORT_SM_REQFAIL	= 7,	/* request failure            */ +	BFA_DPORT_SM_SCN	= 8,	/* state change notify frm fw */ +}; + +static void bfa_dport_sm_disabled(struct bfa_dport_s *dport, +				  enum bfa_dport_sm_event event); +static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport, +				  enum bfa_dport_sm_event event); +static void bfa_dport_sm_enabling(struct bfa_dport_s *dport, +				  enum bfa_dport_sm_event event); +static void bfa_dport_sm_enabled(struct bfa_dport_s *dport, +				 enum bfa_dport_sm_event event); +static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport, +				 enum bfa_dport_sm_event event); +static void bfa_dport_sm_disabling(struct bfa_dport_s *dport, +				   enum bfa_dport_sm_event event); +static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport, +					enum bfa_dport_sm_event event); +static void bfa_dport_sm_starting(struct bfa_dport_s *dport, +				  enum bfa_dport_sm_event event); +static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport, +				   enum bfa_dport_sm_event event); +static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport, +				   enum bfa_dport_sm_event event); +static void bfa_dport_qresume(void *cbarg); +static void bfa_dport_req_comp(struct bfa_dport_s *dport, +				struct bfi_diag_dport_rsp_s *msg); +static void bfa_dport_scn(struct bfa_dport_s *dport, +				struct bfi_diag_dport_scn_s *msg); + +/* + *	BFA fcdiag module + */ +#define BFA_DIAG_QTEST_TOV	1000    /* msec */ + +/* + *	Set port status to busy + */ +static void +bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag) +{ +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa); + +	if (fcdiag->lb.lock) +		fcport->diag_busy = BFA_TRUE; +	else +		fcport->diag_busy = BFA_FALSE; +} + +static void +bfa_fcdiag_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, +		struct bfa_s *bfa) +{ +} + +static void +bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, +		struct bfa_pcidev_s *pcidev) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	struct bfa_dport_s  *dport = &fcdiag->dport; + +	fcdiag->bfa             = bfa; +	fcdiag->trcmod  = bfa->trcmod; +	/* The common DIAG attach bfa_diag_attach() will do all memory claim */ +	dport->bfa = bfa; +	bfa_sm_set_state(dport, bfa_dport_sm_disabled); +	bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport); +	dport->cbfn = NULL; +	dport->cbarg = NULL; +	dport->test_state = BFA_DPORT_ST_DISABLED; +	memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s)); +} + +static void +bfa_fcdiag_iocdisable(struct bfa_s *bfa) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	struct bfa_dport_s *dport = &fcdiag->dport; + +	bfa_trc(fcdiag, fcdiag->lb.lock); +	if (fcdiag->lb.lock) { +		fcdiag->lb.status = BFA_STATUS_IOC_FAILURE; +		fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status); +		fcdiag->lb.lock = 0; +		bfa_fcdiag_set_busy_status(fcdiag); +	} + +	bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL); +} + +static void +bfa_fcdiag_detach(struct bfa_s *bfa) +{ +} + +static void +bfa_fcdiag_start(struct bfa_s *bfa) +{ +} + +static void +bfa_fcdiag_stop(struct bfa_s *bfa) +{ +} + +static void +bfa_fcdiag_queuetest_timeout(void *cbarg) +{ +	struct bfa_fcdiag_s       *fcdiag = cbarg; +	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result; + +	bfa_trc(fcdiag, fcdiag->qtest.all); +	bfa_trc(fcdiag, fcdiag->qtest.count); + +	fcdiag->qtest.timer_active = 0; + +	res->status = BFA_STATUS_ETIMER; +	res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count; +	if (fcdiag->qtest.all) +		res->queue  = fcdiag->qtest.all; + +	bfa_trc(fcdiag, BFA_STATUS_ETIMER); +	fcdiag->qtest.status = BFA_STATUS_ETIMER; +	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status); +	fcdiag->qtest.lock = 0; +} + +static bfa_status_t +bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag) +{ +	u32	i; +	struct bfi_diag_qtest_req_s *req; + +	req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue); +	if (!req) +		return BFA_STATUS_DEVBUSY; + +	/* build host command */ +	bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST, +		bfa_fn_lpu(fcdiag->bfa)); + +	for (i = 0; i < BFI_LMSG_PL_WSZ; i++) +		req->data[i] = QTEST_PAT_DEFAULT; + +	bfa_trc(fcdiag, fcdiag->qtest.queue); +	/* ring door bell */ +	bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh); +	return BFA_STATUS_OK; +} + +static void +bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag, +			bfi_diag_qtest_rsp_t *rsp) +{ +	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result; +	bfa_status_t status = BFA_STATUS_OK; +	int i; + +	/* Check timer, should still be active   */ +	if (!fcdiag->qtest.timer_active) { +		bfa_trc(fcdiag, fcdiag->qtest.timer_active); +		return; +	} + +	/* update count */ +	fcdiag->qtest.count--; + +	/* Check result */ +	for (i = 0; i < BFI_LMSG_PL_WSZ; i++) { +		if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) { +			res->status = BFA_STATUS_DATACORRUPTED; +			break; +		} +	} + +	if (res->status == BFA_STATUS_OK) { +		if (fcdiag->qtest.count > 0) { +			status = bfa_fcdiag_queuetest_send(fcdiag); +			if (status == BFA_STATUS_OK) +				return; +			else +				res->status = status; +		} else if (fcdiag->qtest.all > 0 && +			fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) { +			fcdiag->qtest.count = QTEST_CNT_DEFAULT; +			fcdiag->qtest.queue++; +			status = bfa_fcdiag_queuetest_send(fcdiag); +			if (status == BFA_STATUS_OK) +				return; +			else +				res->status = status; +		} +	} + +	/* Stop timer when we comp all queue */ +	if (fcdiag->qtest.timer_active) { +		bfa_timer_stop(&fcdiag->qtest.timer); +		fcdiag->qtest.timer_active = 0; +	} +	res->queue = fcdiag->qtest.queue; +	res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count; +	bfa_trc(fcdiag, res->count); +	bfa_trc(fcdiag, res->status); +	fcdiag->qtest.status = res->status; +	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status); +	fcdiag->qtest.lock = 0; +} + +static void +bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag, +			struct bfi_diag_lb_rsp_s *rsp) +{ +	struct bfa_diag_loopback_result_s *res = fcdiag->lb.result; + +	res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm); +	res->numosffrm  = be32_to_cpu(rsp->res.numosffrm); +	res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm); +	res->badfrminf  = be32_to_cpu(rsp->res.badfrminf); +	res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum); +	res->status     = rsp->res.status; +	fcdiag->lb.status = rsp->res.status; +	bfa_trc(fcdiag, fcdiag->lb.status); +	fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status); +	fcdiag->lb.lock = 0; +	bfa_fcdiag_set_busy_status(fcdiag); +} + +static bfa_status_t +bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag, +			struct bfa_diag_loopback_s *loopback) +{ +	struct bfi_diag_lb_req_s *lb_req; + +	lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG); +	if (!lb_req) +		return BFA_STATUS_DEVBUSY; + +	/* build host command */ +	bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK, +		bfa_fn_lpu(fcdiag->bfa)); + +	lb_req->lb_mode = loopback->lb_mode; +	lb_req->speed = loopback->speed; +	lb_req->loopcnt = loopback->loopcnt; +	lb_req->pattern = loopback->pattern; + +	/* ring door bell */ +	bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh); + +	bfa_trc(fcdiag, loopback->lb_mode); +	bfa_trc(fcdiag, loopback->speed); +	bfa_trc(fcdiag, loopback->loopcnt); +	bfa_trc(fcdiag, loopback->pattern); +	return BFA_STATUS_OK; +} + +/* + *	cpe/rme intr handler + */ +void +bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); + +	switch (msg->mhdr.msg_id) { +	case BFI_DIAG_I2H_LOOPBACK: +		bfa_fcdiag_loopback_comp(fcdiag, +				(struct bfi_diag_lb_rsp_s *) msg); +		break; +	case BFI_DIAG_I2H_QTEST: +		bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg); +		break; +	case BFI_DIAG_I2H_DPORT: +		bfa_dport_req_comp(&fcdiag->dport, +				(struct bfi_diag_dport_rsp_s *)msg); +		break; +	case BFI_DIAG_I2H_DPORT_SCN: +		bfa_dport_scn(&fcdiag->dport, +				(struct bfi_diag_dport_scn_s *)msg); +		break; +	default: +		bfa_trc(fcdiag, msg->mhdr.msg_id); +		WARN_ON(1); +	} +} + +/* + *	Loopback test + * + *   @param[in] *bfa            - bfa data struct + *   @param[in] opmode          - port operation mode + *   @param[in] speed           - port speed + *   @param[in] lpcnt           - loop count + *   @param[in] pat                     - pattern to build packet + *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct + *   @param[in] cbfn            - callback function + *   @param[in] cbarg           - callback functioin arg + * + *   @param[out] + */ +bfa_status_t +bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode, +		enum bfa_port_speed speed, u32 lpcnt, u32 pat, +		struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn, +		void *cbarg) +{ +	struct  bfa_diag_loopback_s loopback; +	struct bfa_port_attr_s attr; +	bfa_status_t status; +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); + +	if (!bfa_iocfc_is_operational(bfa)) +		return BFA_STATUS_IOC_NON_OP; + +	/* if port is PBC disabled, return error */ +	if (bfa_fcport_is_pbcdisabled(bfa)) { +		bfa_trc(fcdiag, BFA_STATUS_PBC); +		return BFA_STATUS_PBC; +	} + +	if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) { +		bfa_trc(fcdiag, opmode); +		return BFA_STATUS_PORT_NOT_DISABLED; +	} + +	/* +	 * Check if input speed is supported by the port mode +	 */ +	if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) { +		if (!(speed == BFA_PORT_SPEED_1GBPS || +		      speed == BFA_PORT_SPEED_2GBPS || +		      speed == BFA_PORT_SPEED_4GBPS || +		      speed == BFA_PORT_SPEED_8GBPS || +		      speed == BFA_PORT_SPEED_16GBPS || +		      speed == BFA_PORT_SPEED_AUTO)) { +			bfa_trc(fcdiag, speed); +			return BFA_STATUS_UNSUPP_SPEED; +		} +		bfa_fcport_get_attr(bfa, &attr); +		bfa_trc(fcdiag, attr.speed_supported); +		if (speed > attr.speed_supported) +			return BFA_STATUS_UNSUPP_SPEED; +	} else { +		if (speed != BFA_PORT_SPEED_10GBPS) { +			bfa_trc(fcdiag, speed); +			return BFA_STATUS_UNSUPP_SPEED; +		} +	} + +	/* +	 * For CT2, 1G is not supported +	 */ +	if ((speed == BFA_PORT_SPEED_1GBPS) && +	    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) { +		bfa_trc(fcdiag, speed); +		return BFA_STATUS_UNSUPP_SPEED; +	} + +	/* For Mezz card, port speed entered needs to be checked */ +	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) { +		if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) { +			if (!(speed == BFA_PORT_SPEED_1GBPS || +			      speed == BFA_PORT_SPEED_2GBPS || +			      speed == BFA_PORT_SPEED_4GBPS || +			      speed == BFA_PORT_SPEED_8GBPS || +			      speed == BFA_PORT_SPEED_16GBPS || +			      speed == BFA_PORT_SPEED_AUTO)) +				return BFA_STATUS_UNSUPP_SPEED; +		} else { +			if (speed != BFA_PORT_SPEED_10GBPS) +				return BFA_STATUS_UNSUPP_SPEED; +		} +	} +	/* check to see if fcport is dport */ +	if (bfa_fcport_is_dport(bfa)) { +		bfa_trc(fcdiag, fcdiag->lb.lock); +		return BFA_STATUS_DPORT_ENABLED; +	} +	/* check to see if there is another destructive diag cmd running */ +	if (fcdiag->lb.lock) { +		bfa_trc(fcdiag, fcdiag->lb.lock); +		return BFA_STATUS_DEVBUSY; +	} + +	fcdiag->lb.lock = 1; +	loopback.lb_mode = opmode; +	loopback.speed = speed; +	loopback.loopcnt = lpcnt; +	loopback.pattern = pat; +	fcdiag->lb.result = result; +	fcdiag->lb.cbfn = cbfn; +	fcdiag->lb.cbarg = cbarg; +	memset(result, 0, sizeof(struct bfa_diag_loopback_result_s)); +	bfa_fcdiag_set_busy_status(fcdiag); + +	/* Send msg to fw */ +	status = bfa_fcdiag_loopback_send(fcdiag, &loopback); +	return status; +} + +/* + *	DIAG queue test command + * + *   @param[in] *bfa            - bfa data struct + *   @param[in] force           - 1: don't do ioc op checking + *   @param[in] queue           - queue no. to test + *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct + *   @param[in] cbfn            - callback function + *   @param[in] *cbarg          - callback functioin arg + * + *   @param[out] + */ +bfa_status_t +bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue, +		struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn, +		void *cbarg) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	bfa_status_t status; +	bfa_trc(fcdiag, force); +	bfa_trc(fcdiag, queue); + +	if (!force && !bfa_iocfc_is_operational(bfa)) +		return BFA_STATUS_IOC_NON_OP; + +	/* check to see if there is another destructive diag cmd running */ +	if (fcdiag->qtest.lock) { +		bfa_trc(fcdiag, fcdiag->qtest.lock); +		return BFA_STATUS_DEVBUSY; +	} + +	/* Initialization */ +	fcdiag->qtest.lock = 1; +	fcdiag->qtest.cbfn = cbfn; +	fcdiag->qtest.cbarg = cbarg; +	fcdiag->qtest.result = result; +	fcdiag->qtest.count = QTEST_CNT_DEFAULT; + +	/* Init test results */ +	fcdiag->qtest.result->status = BFA_STATUS_OK; +	fcdiag->qtest.result->count  = 0; + +	/* send */ +	if (queue < BFI_IOC_MAX_CQS) { +		fcdiag->qtest.result->queue  = (u8)queue; +		fcdiag->qtest.queue = (u8)queue; +		fcdiag->qtest.all   = 0; +	} else { +		fcdiag->qtest.result->queue  = 0; +		fcdiag->qtest.queue = 0; +		fcdiag->qtest.all   = 1; +	} +	status = bfa_fcdiag_queuetest_send(fcdiag); + +	/* Start a timer */ +	if (status == BFA_STATUS_OK) { +		bfa_timer_start(bfa, &fcdiag->qtest.timer, +				bfa_fcdiag_queuetest_timeout, fcdiag, +				BFA_DIAG_QTEST_TOV); +		fcdiag->qtest.timer_active = 1; +	} +	return status; +} + +/* + * DIAG PLB is running + * + *   @param[in] *bfa    - bfa data struct + * + *   @param[out] + */ +bfa_status_t +bfa_fcdiag_lb_is_running(struct bfa_s *bfa) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK; +} + +/* + *	D-port + */ +#define bfa_dport_result_start(__dport, __mode) do {			\ +		(__dport)->result.start_time = bfa_get_log_time();	\ +		(__dport)->result.status = DPORT_TEST_ST_INPRG;		\ +		(__dport)->result.mode = (__mode);			\ +		(__dport)->result.rp_pwwn = (__dport)->rp_pwwn;		\ +		(__dport)->result.rp_nwwn = (__dport)->rp_nwwn;		\ +		(__dport)->result.lpcnt = (__dport)->lpcnt;		\ +} while (0) + +static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport, +					enum bfi_dport_req req); +static void +bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status) +{ +	if (dport->cbfn != NULL) { +		dport->cbfn(dport->cbarg, bfa_status); +		dport->cbfn = NULL; +		dport->cbarg = NULL; +	} +} + +static void +bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_ENABLE: +		bfa_fcport_dportenable(dport->bfa); +		if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE)) +			bfa_sm_set_state(dport, bfa_dport_sm_enabling); +		else +			bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait); +		break; + +	case BFA_DPORT_SM_DISABLE: +		/* Already disabled */ +		break; + +	case BFA_DPORT_SM_HWFAIL: +		/* ignore */ +		break; + +	case BFA_DPORT_SM_SCN: +		if (dport->i2hmsg.scn.state ==  BFI_DPORT_SCN_DDPORT_ENABLE) { +			bfa_fcport_ddportenable(dport->bfa); +			dport->dynamic = BFA_TRUE; +			dport->test_state = BFA_DPORT_ST_NOTSTART; +			bfa_sm_set_state(dport, bfa_dport_sm_enabled); +		} else { +			bfa_trc(dport->bfa, dport->i2hmsg.scn.state); +			WARN_ON(1); +		} +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport, +			    enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_QRESUME: +		bfa_sm_set_state(dport, bfa_dport_sm_enabling); +		bfa_dport_send_req(dport, BFI_DPORT_ENABLE); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_reqq_wcancel(&dport->reqq_wait); +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_FWRSP: +		memset(&dport->result, 0, +				sizeof(struct bfa_diag_dport_result_s)); +		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) { +			dport->test_state = BFA_DPORT_ST_NO_SFP; +		} else { +			dport->test_state = BFA_DPORT_ST_INP; +			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO); +		} +		bfa_sm_set_state(dport, bfa_dport_sm_enabled); +		break; + +	case BFA_DPORT_SM_REQFAIL: +		dport->test_state = BFA_DPORT_ST_DISABLED; +		bfa_fcport_dportdisable(dport->bfa); +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_START: +		if (bfa_dport_send_req(dport, BFI_DPORT_START)) +			bfa_sm_set_state(dport, bfa_dport_sm_starting); +		else +			bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait); +		break; + +	case BFA_DPORT_SM_DISABLE: +		bfa_fcport_dportdisable(dport->bfa); +		if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE)) +			bfa_sm_set_state(dport, bfa_dport_sm_disabling); +		else +			bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		break; + +	case BFA_DPORT_SM_SCN: +		switch (dport->i2hmsg.scn.state) { +		case BFI_DPORT_SCN_TESTCOMP: +			dport->test_state = BFA_DPORT_ST_COMP; +			break; + +		case BFI_DPORT_SCN_TESTSTART: +			dport->test_state = BFA_DPORT_ST_INP; +			break; + +		case BFI_DPORT_SCN_TESTSKIP: +		case BFI_DPORT_SCN_SUBTESTSTART: +			/* no state change */ +			break; + +		case BFI_DPORT_SCN_SFP_REMOVED: +			dport->test_state = BFA_DPORT_ST_NO_SFP; +			break; + +		case BFI_DPORT_SCN_DDPORT_DISABLE: +			bfa_fcport_ddportdisable(dport->bfa); + +			if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE)) +				bfa_sm_set_state(dport, +					 bfa_dport_sm_dynamic_disabling); +			else +				bfa_sm_set_state(dport, +					 bfa_dport_sm_dynamic_disabling_qwait); +			break; + +		case BFI_DPORT_SCN_FCPORT_DISABLE: +			bfa_fcport_ddportdisable(dport->bfa); + +			bfa_sm_set_state(dport, bfa_dport_sm_disabled); +			dport->dynamic = BFA_FALSE; +			break; + +		default: +			bfa_trc(dport->bfa, dport->i2hmsg.scn.state); +			bfa_sm_fault(dport->bfa, event); +		} +		break; +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport, +			     enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_QRESUME: +		bfa_sm_set_state(dport, bfa_dport_sm_disabling); +		bfa_dport_send_req(dport, BFI_DPORT_DISABLE); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_reqq_wcancel(&dport->reqq_wait); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); +		break; + +	case BFA_DPORT_SM_SCN: +		/* ignore */ +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_FWRSP: +		dport->test_state = BFA_DPORT_ST_DISABLED; +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); +		break; + +	case BFA_DPORT_SM_SCN: +		/* no state change */ +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport, +			    enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_QRESUME: +		bfa_sm_set_state(dport, bfa_dport_sm_starting); +		bfa_dport_send_req(dport, BFI_DPORT_START); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_reqq_wcancel(&dport->reqq_wait); +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_FWRSP: +		memset(&dport->result, 0, +				sizeof(struct bfa_diag_dport_result_s)); +		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) { +			dport->test_state = BFA_DPORT_ST_NO_SFP; +		} else { +			dport->test_state = BFA_DPORT_ST_INP; +			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU); +		} +		/* fall thru */ + +	case BFA_DPORT_SM_REQFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_enabled); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED); +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport, +			       enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_SCN: +		switch (dport->i2hmsg.scn.state) { +		case BFI_DPORT_SCN_DDPORT_DISABLED: +			bfa_sm_set_state(dport, bfa_dport_sm_disabled); +			dport->dynamic = BFA_FALSE; +			bfa_fcport_enable(dport->bfa); +			break; + +		default: +			bfa_trc(dport->bfa, dport->i2hmsg.scn.state); +			bfa_sm_fault(dport->bfa, event); + +		} +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static void +bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport, +			    enum bfa_dport_sm_event event) +{ +	bfa_trc(dport->bfa, event); + +	switch (event) { +	case BFA_DPORT_SM_QRESUME: +		bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling); +		bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE); +		break; + +	case BFA_DPORT_SM_HWFAIL: +		bfa_sm_set_state(dport, bfa_dport_sm_disabled); +		bfa_reqq_wcancel(&dport->reqq_wait); +		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK); +		break; + +	case BFA_DPORT_SM_SCN: +		/* ignore */ +		break; + +	default: +		bfa_sm_fault(dport->bfa, event); +	} +} + +static bfa_boolean_t +bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req) +{ +	struct bfi_diag_dport_req_s *m; + +	/* +	 * check for room in queue to send request now +	 */ +	m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG); +	if (!m) { +		bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait); +		return BFA_FALSE; +	} + +	bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT, +		    bfa_fn_lpu(dport->bfa)); +	m->req  = req; +	if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) { +		m->lpcnt = cpu_to_be32(dport->lpcnt); +		m->payload = cpu_to_be32(dport->payload); +	} + +	/* +	 * queue I/O message to firmware +	 */ +	bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh); + +	return BFA_TRUE; +} + +static void +bfa_dport_qresume(void *cbarg) +{ +	struct bfa_dport_s *dport = cbarg; + +	bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME); +} + +static void +bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg) +{ +	msg->status = cpu_to_be32(msg->status); +	dport->i2hmsg.rsp.status = msg->status; +	dport->rp_pwwn = msg->pwwn; +	dport->rp_nwwn = msg->nwwn; + +	if ((msg->status == BFA_STATUS_OK) || +	    (msg->status == BFA_STATUS_DPORT_NO_SFP)) { +		bfa_trc(dport->bfa, msg->status); +		bfa_trc(dport->bfa, dport->rp_pwwn); +		bfa_trc(dport->bfa, dport->rp_nwwn); +		bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP); + +	} else { +		bfa_trc(dport->bfa, msg->status); +		bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL); +	} +	bfa_cb_fcdiag_dport(dport, msg->status); +} + +static bfa_boolean_t +bfa_dport_is_sending_req(struct bfa_dport_s *dport) +{ +	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling)	|| +	    bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) || +	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling)	|| +	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) || +	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting)	|| +	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) { +		return BFA_TRUE; +	} else { +		return BFA_FALSE; +	} +} + +static void +bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg) +{ +	int i; +	uint8_t subtesttype; + +	bfa_trc(dport->bfa, msg->state); +	dport->i2hmsg.scn.state = msg->state; + +	switch (dport->i2hmsg.scn.state) { +	case BFI_DPORT_SCN_TESTCOMP: +		dport->result.end_time = bfa_get_log_time(); +		bfa_trc(dport->bfa, dport->result.end_time); + +		dport->result.status = msg->info.testcomp.status; +		bfa_trc(dport->bfa, dport->result.status); + +		dport->result.roundtrip_latency = +			cpu_to_be32(msg->info.testcomp.latency); +		dport->result.est_cable_distance = +			cpu_to_be32(msg->info.testcomp.distance); +		dport->result.buffer_required = +			be16_to_cpu(msg->info.testcomp.numbuffer); + +		dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz); +		dport->result.speed = msg->info.testcomp.speed; + +		bfa_trc(dport->bfa, dport->result.roundtrip_latency); +		bfa_trc(dport->bfa, dport->result.est_cable_distance); +		bfa_trc(dport->bfa, dport->result.buffer_required); +		bfa_trc(dport->bfa, dport->result.frmsz); +		bfa_trc(dport->bfa, dport->result.speed); + +		for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) { +			dport->result.subtest[i].status = +				msg->info.testcomp.subtest_status[i]; +			bfa_trc(dport->bfa, dport->result.subtest[i].status); +		} +		break; + +	case BFI_DPORT_SCN_TESTSKIP: +	case BFI_DPORT_SCN_DDPORT_ENABLE: +		memset(&dport->result, 0, +				sizeof(struct bfa_diag_dport_result_s)); +		break; + +	case BFI_DPORT_SCN_TESTSTART: +		memset(&dport->result, 0, +				sizeof(struct bfa_diag_dport_result_s)); +		dport->rp_pwwn = msg->info.teststart.pwwn; +		dport->rp_nwwn = msg->info.teststart.nwwn; +		dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm); +		bfa_dport_result_start(dport, msg->info.teststart.mode); +		break; + +	case BFI_DPORT_SCN_SUBTESTSTART: +		subtesttype = msg->info.teststart.type; +		dport->result.subtest[subtesttype].start_time = +			bfa_get_log_time(); +		dport->result.subtest[subtesttype].status = +			DPORT_TEST_ST_INPRG; + +		bfa_trc(dport->bfa, subtesttype); +		bfa_trc(dport->bfa, +			dport->result.subtest[subtesttype].start_time); +		break; + +	case BFI_DPORT_SCN_SFP_REMOVED: +	case BFI_DPORT_SCN_DDPORT_DISABLED: +	case BFI_DPORT_SCN_DDPORT_DISABLE: +	case BFI_DPORT_SCN_FCPORT_DISABLE: +		dport->result.status = DPORT_TEST_ST_IDLE; +		break; + +	default: +		bfa_sm_fault(dport->bfa, msg->state); +	} + +	bfa_sm_send_event(dport, BFA_DPORT_SM_SCN); +} + +/* + * Dport enable + * + * @param[in] *bfa            - bfa data struct + */ +bfa_status_t +bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat, +				bfa_cb_diag_t cbfn, void *cbarg) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	struct bfa_dport_s  *dport = &fcdiag->dport; + +	/* +	 * Dport is not support in MEZZ card +	 */ +	if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) { +		bfa_trc(dport->bfa, BFA_STATUS_PBC); +		return BFA_STATUS_CMD_NOTSUPP_MEZZ; +	} + +	/* +	 * Dport is supported in CT2 or above +	 */ +	if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) { +		bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id); +		return BFA_STATUS_FEATURE_NOT_SUPPORTED; +	} + +	/* +	 * Check to see if IOC is down +	*/ +	if (!bfa_iocfc_is_operational(bfa)) +		return BFA_STATUS_IOC_NON_OP; + +	/* if port is PBC disabled, return error */ +	if (bfa_fcport_is_pbcdisabled(bfa)) { +		bfa_trc(dport->bfa, BFA_STATUS_PBC); +		return BFA_STATUS_PBC; +	} + +	/* +	 * Check if port mode is FC port +	 */ +	if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) { +		bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc)); +		return BFA_STATUS_CMD_NOTSUPP_CNA; +	} + +	/* +	 * Check if port is in LOOP mode +	 */ +	if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) || +	    (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_TOPOLOGY_LOOP; +	} + +	/* +	 * Check if port is TRUNK mode +	 */ +	if (bfa_fcport_is_trunk_enabled(bfa)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_ERROR_TRUNK_ENABLED; +	} + +	/* +	 * Check if diag loopback is running +	 */ +	if (bfa_fcdiag_lb_is_running(bfa)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_DIAG_BUSY; +	} + +	/* +	 * Check to see if port is disable or in dport state +	 */ +	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) && +	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_PORT_NOT_DISABLED; +	} + +	/* +	 * Check if dport is in dynamic mode +	 */ +	if (dport->dynamic) +		return BFA_STATUS_DDPORT_ERR; + +	/* +	 * Check if dport is busy +	 */ +	if (bfa_dport_is_sending_req(dport)) +		return BFA_STATUS_DEVBUSY; + +	/* +	 * Check if dport is already enabled +	 */ +	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_DPORT_ENABLED; +	} + +	bfa_trc(dport->bfa, lpcnt); +	bfa_trc(dport->bfa, pat); +	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT; +	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT; +	dport->cbfn = cbfn; +	dport->cbarg = cbarg; + +	bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE); +	return BFA_STATUS_OK; +} + +/* + *	Dport disable + * + *	@param[in] *bfa            - bfa data struct + */ +bfa_status_t +bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	struct bfa_dport_s *dport = &fcdiag->dport; + +	if (bfa_ioc_is_disabled(&bfa->ioc)) +		return BFA_STATUS_IOC_DISABLED; + +	/* if port is PBC disabled, return error */ +	if (bfa_fcport_is_pbcdisabled(bfa)) { +		bfa_trc(dport->bfa, BFA_STATUS_PBC); +		return BFA_STATUS_PBC; +	} + +	/* +	 * Check if dport is in dynamic mode +	 */ +	if (dport->dynamic) { +		return BFA_STATUS_DDPORT_ERR; +	} + +	/* +	 * Check to see if port is disable or in dport state +	 */ +	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) && +	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_PORT_NOT_DISABLED; +	} + +	/* +	 * Check if dport is busy +	 */ +	if (bfa_dport_is_sending_req(dport)) +		return BFA_STATUS_DEVBUSY; + +	/* +	 * Check if dport is already disabled +	 */ +	if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_DPORT_DISABLED; +	} + +	dport->cbfn = cbfn; +	dport->cbarg = cbarg; + +	bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE); +	return BFA_STATUS_OK; +} + +/* + * Dport start -- restart dport test + * + *   @param[in] *bfa		- bfa data struct + */ +bfa_status_t +bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat, +			bfa_cb_diag_t cbfn, void *cbarg) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	struct bfa_dport_s *dport = &fcdiag->dport; + +	/* +	 * Check to see if IOC is down +	 */ +	if (!bfa_iocfc_is_operational(bfa)) +		return BFA_STATUS_IOC_NON_OP; + +	/* +	 * Check if dport is in dynamic mode +	 */ +	if (dport->dynamic) +		return BFA_STATUS_DDPORT_ERR; + +	/* +	 * Check if dport is busy +	 */ +	if (bfa_dport_is_sending_req(dport)) +		return BFA_STATUS_DEVBUSY; + +	/* +	 * Check if dport is in enabled state. +	 * Test can only be restart when previous test has completed +	 */ +	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_DPORT_DISABLED; + +	} else { +		if (dport->test_state == BFA_DPORT_ST_NO_SFP) +			return BFA_STATUS_DPORT_INV_SFP; + +		if (dport->test_state == BFA_DPORT_ST_INP) +			return BFA_STATUS_DEVBUSY; + +		WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);  	} + +	bfa_trc(dport->bfa, lpcnt); +	bfa_trc(dport->bfa, pat); + +	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT; +	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT; + +	dport->cbfn = cbfn; +	dport->cbarg = cbarg; + +	bfa_sm_send_event(dport, BFA_DPORT_SM_START); +	return BFA_STATUS_OK;  } +/* + * Dport show -- return dport test result + * + *   @param[in] *bfa		- bfa data struct + */ +bfa_status_t +bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result) +{ +	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa); +	struct bfa_dport_s *dport = &fcdiag->dport; + +	/* +	 * Check to see if IOC is down +	 */ +	if (!bfa_iocfc_is_operational(bfa)) +		return BFA_STATUS_IOC_NON_OP; + +	/* +	 * Check if dport is busy +	 */ +	if (bfa_dport_is_sending_req(dport)) +		return BFA_STATUS_DEVBUSY; +	/* +	 * Check if dport is in enabled state. +	 */ +	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) { +		bfa_trc(dport->bfa, 0); +		return BFA_STATUS_DPORT_DISABLED; + +	} + +	/* +	 * Check if there is SFP +	 */ +	if (dport->test_state == BFA_DPORT_ST_NO_SFP) +		return BFA_STATUS_DPORT_INV_SFP; + +	memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s)); + +	return BFA_STATUS_OK; +} diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index e2349d5cdb9..ef07365991e 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -26,6 +26,7 @@   * Scatter-gather DMA related defines   */  #define BFA_SGPG_MIN	(16) +#define BFA_SGPG_MAX	(8192)  /*   * Alignment macro for SG page allocation @@ -54,17 +55,21 @@ struct bfa_sgpg_s {   */  #define BFA_SGPG_NPAGE(_nsges)  (((_nsges) / BFI_SGPG_DATA_SGES) + 1) +/* Max SGPG dma segs required */ +#define BFA_SGPG_DMA_SEGS	\ +	BFI_MEM_DMA_NSEGS(BFA_SGPG_MAX, (uint32_t)sizeof(struct bfi_sgpg_s)) +  struct bfa_sgpg_mod_s {  	struct bfa_s *bfa;  	int		num_sgpgs;	/*  number of SG pages		*/  	int		free_sgpgs;	/*  number of free SG pages	*/ -	struct bfa_sgpg_s	*hsgpg_arr;	/*  BFA SG page array	*/ -	struct bfi_sgpg_s *sgpg_arr;	/*  actual SG page array	*/ -	u64	sgpg_arr_pa;	/*  SG page array DMA addr	*/  	struct list_head	sgpg_q;		/*  queue of free SG pages */  	struct list_head	sgpg_wait_q;	/*  wait queue for SG pages */ +	struct bfa_mem_dma_s	dma_seg[BFA_SGPG_DMA_SEGS]; +	struct bfa_mem_kva_s	kva_seg;  };  #define BFA_SGPG_MOD(__bfa)	(&(__bfa)->modules.sgpg_mod) +#define BFA_MEM_SGPG_KVA(__bfa) (&(BFA_SGPG_MOD(__bfa)->kva_seg))  bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,  			     int nsgpgs); @@ -79,26 +84,35 @@ void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);   * FCXP related defines   */  #define BFA_FCXP_MIN		(1) +#define BFA_FCXP_MAX		(256)  #define BFA_FCXP_MAX_IBUF_SZ	(2 * 1024 + 256)  #define BFA_FCXP_MAX_LBUF_SZ	(4 * 1024 + 256) +/* Max FCXP dma segs required */ +#define BFA_FCXP_DMA_SEGS						\ +	BFI_MEM_DMA_NSEGS(BFA_FCXP_MAX,					\ +		(u32)BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ) +  struct bfa_fcxp_mod_s {  	struct bfa_s      *bfa;		/* backpointer to BFA */  	struct bfa_fcxp_s *fcxp_list;	/* array of FCXPs */  	u16	num_fcxps;	/* max num FCXP requests */ -	struct list_head  fcxp_free_q;	/* free FCXPs */ -	struct list_head  fcxp_active_q;	/* active FCXPs */ -	void		*req_pld_list_kva;	/* list of FCXP req pld */ -	u64	req_pld_list_pa;	/* list of FCXP req pld */ -	void		*rsp_pld_list_kva;	/* list of FCXP resp pld */ -	u64	rsp_pld_list_pa;	/* list of FCXP resp pld */ -	struct list_head  wait_q;		/* wait queue for free fcxp */ +	struct list_head fcxp_req_free_q; /* free FCXPs used for sending req */ +	struct list_head fcxp_rsp_free_q; /* free FCXPs used for sending req */ +	struct list_head fcxp_active_q;	/* active FCXPs */ +	struct list_head req_wait_q;	/* wait queue for free req_fcxp */ +	struct list_head rsp_wait_q;	/* wait queue for free rsp_fcxp */ +	struct list_head fcxp_req_unused_q;	/* unused req_fcxps */ +	struct list_head fcxp_rsp_unused_q;	/* unused rsp_fcxps */  	u32	req_pld_sz;  	u32	rsp_pld_sz; +	struct bfa_mem_dma_s dma_seg[BFA_FCXP_DMA_SEGS]; +	struct bfa_mem_kva_s kva_seg;  };  #define BFA_FCXP_MOD(__bfa)		(&(__bfa)->modules.fcxp_mod)  #define BFA_FCXP_FROM_TAG(__mod, __tag)	(&(__mod)->fcxp_list[__tag]) +#define BFA_MEM_FCXP_KVA(__bfa) (&(BFA_FCXP_MOD(__bfa)->kva_seg))  typedef void    (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,  				   void *cb_arg, bfa_status_t req_status, @@ -127,7 +141,7 @@ struct bfa_fcxp_req_info_s {  					 * rport nexus is established  					 */  	struct fchs_s	fchs;	/*  request FC header structure */ -	u8		cts;	/*  continous sequence */ +	u8		cts;	/*  continuous sequence */  	u8		class;	/*  FC class for the request/response */  	u16	max_frmsz;	/*  max send frame size */  	u16	vf_id;	/*  vsan tag if applicable */ @@ -186,6 +200,7 @@ struct bfa_fcxp_s {  	struct bfa_cb_qe_s    hcb_qe;	/*  comp: callback qelem */  	struct bfa_reqq_wait_s	reqq_wqe;  	bfa_boolean_t	reqq_waiting; +	bfa_boolean_t	req_rsp;	/* Used to track req/rsp fcxp */  };  struct bfa_fcxp_wqe_s { @@ -206,13 +221,15 @@ struct bfa_fcxp_wqe_s {  #define BFA_FCXP_RSP_FCHS(_fcxp)	(&((_fcxp)->rsp_info.fchs))  #define BFA_FCXP_RSP_PLD(_fcxp)		(bfa_fcxp_get_rspbuf(_fcxp)) -#define BFA_FCXP_REQ_PLD_PA(_fcxp)				\ -	((_fcxp)->fcxp_mod->req_pld_list_pa +			\ -	 ((_fcxp)->fcxp_mod->req_pld_sz  * (_fcxp)->fcxp_tag)) +#define BFA_FCXP_REQ_PLD_PA(_fcxp)					      \ +	bfa_mem_get_dmabuf_pa((_fcxp)->fcxp_mod, (_fcxp)->fcxp_tag,	      \ +		(_fcxp)->fcxp_mod->req_pld_sz + (_fcxp)->fcxp_mod->rsp_pld_sz) -#define BFA_FCXP_RSP_PLD_PA(_fcxp)				\ -	((_fcxp)->fcxp_mod->rsp_pld_list_pa +			\ -	 ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag)) +/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */ +#define BFA_FCXP_RSP_PLD_PA(_fcxp)					       \ +	(bfa_mem_get_dmabuf_pa((_fcxp)->fcxp_mod, (_fcxp)->fcxp_tag,	       \ +	      (_fcxp)->fcxp_mod->req_pld_sz + (_fcxp)->fcxp_mod->rsp_pld_sz) + \ +	      (_fcxp)->fcxp_mod->req_pld_sz)  void	bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); @@ -220,16 +237,31 @@ void	bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);  /*   * RPORT related defines   */ +enum bfa_rport_event { +	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event          */ +	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport  */ +	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online             */ +	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline            */ +	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response           */ +	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure             */ +	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware       */ +	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed             */ +	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue      */ +}; +  #define BFA_RPORT_MIN	4  struct bfa_rport_mod_s {  	struct bfa_rport_s *rps_list;	/*  list of rports	*/  	struct list_head	rp_free_q;	/*  free bfa_rports	*/  	struct list_head	rp_active_q;	/*  free bfa_rports	*/ +	struct list_head	rp_unused_q;	/*  unused bfa rports  */  	u16	num_rports;	/*  number of rports	*/ +	struct bfa_mem_kva_s	kva_seg;  };  #define BFA_RPORT_MOD(__bfa)	(&(__bfa)->modules.rport_mod) +#define BFA_MEM_RPORT_KVA(__bfa) (&(BFA_RPORT_MOD(__bfa)->kva_seg))  /*   * Convert rport tag to RPORT @@ -242,6 +274,7 @@ struct bfa_rport_mod_s {   * protected functions   */  void	bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); +void	bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw);  /*   *	BFA rport information. @@ -268,6 +301,7 @@ struct bfa_rport_s {  	void		*rport_drv;	/*  fcs/driver rport object	    */  	u16	fw_handle;	/*  firmware rport handle	    */  	u16	rport_tag;	/*  BFA rport tag		    */ +	u8	lun_mask;	/*  LUN mask flag		    */  	struct bfa_rport_info_s rport_info; /*  rport info from fcs/driver */  	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq     */  	struct bfa_cb_qe_s hcb_qe;	/*  BFA callback qelem		    */ @@ -286,7 +320,7 @@ struct bfa_rport_s {   */  #define BFA_UF_MIN	(4) - +#define BFA_UF_MAX	(256)  struct bfa_uf_s {  	struct list_head	qe;	/*  queue element		*/ @@ -314,36 +348,41 @@ struct bfa_uf_s {   */  typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf); +#define BFA_UF_BUFSZ	(2 * 1024 + 256) + +struct bfa_uf_buf_s { +	u8	d[BFA_UF_BUFSZ]; +}; + +#define BFA_PER_UF_DMA_SZ	\ +	(u32)BFA_ROUNDUP(sizeof(struct bfa_uf_buf_s), BFA_DMA_ALIGN_SZ) + +/* Max UF dma segs required */ +#define BFA_UF_DMA_SEGS BFI_MEM_DMA_NSEGS(BFA_UF_MAX, BFA_PER_UF_DMA_SZ) +  struct bfa_uf_mod_s {  	struct bfa_s *bfa;		/*  back pointer to BFA */  	struct bfa_uf_s *uf_list;	/*  array of UFs */  	u16	num_ufs;	/*  num unsolicited rx frames */  	struct list_head	uf_free_q;	/*  free UFs */  	struct list_head	uf_posted_q;	/*  UFs posted to IOC */ -	struct bfa_uf_buf_s *uf_pbs_kva;	/*  list UF bufs request pld */ -	u64	uf_pbs_pa;	/*  phy addr for UF bufs */ +	struct list_head	uf_unused_q;	/*  unused UF's */  	struct bfi_uf_buf_post_s *uf_buf_posts;  	/*  pre-built UF post msgs */  	bfa_cb_uf_recv_t ufrecv;	/*  uf recv handler function */  	void		*cbarg;		/*  uf receive handler arg */ +	struct bfa_mem_dma_s	dma_seg[BFA_UF_DMA_SEGS]; +	struct bfa_mem_kva_s	kva_seg;  };  #define BFA_UF_MOD(__bfa)	(&(__bfa)->modules.uf_mod) +#define BFA_MEM_UF_KVA(__bfa)	(&(BFA_UF_MOD(__bfa)->kva_seg))  #define ufm_pbs_pa(_ufmod, _uftag)					\ -	((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag)) +	bfa_mem_get_dmabuf_pa(_ufmod, _uftag, BFA_PER_UF_DMA_SZ)  void	bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); - -#define BFA_UF_BUFSZ	(2 * 1024 + 256) - -/* - * @todo private - */ -struct bfa_uf_buf_s { -	u8		d[BFA_UF_BUFSZ]; -}; - +void	bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw);  /*   * LPS - bfa lport login/logout service interface @@ -352,7 +391,8 @@ struct bfa_lps_s {  	struct list_head	qe;	/*  queue element		*/  	struct bfa_s	*bfa;		/*  parent bfa instance	*/  	bfa_sm_t	sm;		/*  finite state machine	*/ -	u8		lp_tag;		/*  lport tag			*/ +	u8		bfa_tag;	/*  lport tag		*/ +	u8		fw_tag;		/*  lport fw tag                */  	u8		reqq;		/*  lport request queue	*/  	u8		alpa;		/*  ALPA for loop topologies	*/  	u32	lp_pid;		/*  lport port ID		*/ @@ -367,6 +407,7 @@ struct bfa_lps_s {  	u16		pr_bbcred;	/*  BB_CREDIT from peer		*/  	u8		lsrjt_rsn;	/*  LSRJT reason		*/  	u8		lsrjt_expl;	/*  LSRJT explanation		*/ +	u8		lun_mask;	/*  LUN mask flag		*/  	wwn_t		pwwn;		/*  port wwn of lport		*/  	wwn_t		nwwn;		/*  node wwn of lport		*/  	wwn_t		pr_pwwn;	/*  port wwn of lport peer	*/ @@ -383,12 +424,15 @@ struct bfa_lps_s {  struct bfa_lps_mod_s {  	struct list_head		lps_free_q;  	struct list_head		lps_active_q; +	struct list_head		lps_login_q;  	struct bfa_lps_s	*lps_arr;  	int			num_lps; +	struct bfa_mem_kva_s	kva_seg;  };  #define BFA_LPS_MOD(__bfa)		(&(__bfa)->modules.lps_mod)  #define BFA_LPS_FROM_TAG(__mod, __tag)	(&(__mod)->lps_arr[__tag]) +#define BFA_MEM_LPS_KVA(__bfa)	(&(BFA_LPS_MOD(__bfa)->kva_seg))  /*   * external functions @@ -401,7 +445,6 @@ void	bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);   */  #define BFA_FCPORT(_bfa)	(&((_bfa)->modules.port)) -typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);  /*   * Link notification data structure @@ -429,9 +472,12 @@ struct bfa_fcport_s {  	/*  supported speeds */  	enum bfa_port_speed speed;	/*  current speed */  	enum bfa_port_topology topology;	/*  current topology */ -	u8			myalpa;	/*  my ALPA in LOOP topology */  	u8			rsvd[3]; +	u8			myalpa;	/*  my ALPA in LOOP topology */ +	u8			alpabm_valid; /* alpa bitmap valid or not */ +	struct fc_alpabm_s	alpabm;	/* alpa bitmap */  	struct bfa_port_cfg_s	cfg;	/*  current port configuration */ +	bfa_boolean_t		use_flash_cfg; /* get port cfg from flash */  	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */  	struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */  	struct bfa_reqq_wait_s	reqq_wait; @@ -454,21 +500,24 @@ struct bfa_fcport_s {  	u8			*stats_kva;  	u64		stats_pa;  	union bfa_fcport_stats_u *stats; -	union bfa_fcport_stats_u *stats_ret; /*  driver stats location */  	bfa_status_t		stats_status; /*  stats/statsclr status */ -	bfa_boolean_t		stats_busy; /*  outstanding stats/statsclr */ +	struct list_head	stats_pending_q; +	struct list_head	statsclr_pending_q;  	bfa_boolean_t		stats_qfull;  	u32		stats_reset_time; /*  stats reset time stamp */ -	bfa_cb_port_t		stats_cbfn; /*  driver callback function */ -	void			*stats_cbarg; /* *!< user callback arg */  	bfa_boolean_t		diag_busy; /*  diag busy status */  	bfa_boolean_t		beacon; /*  port beacon status */  	bfa_boolean_t		link_e2e_beacon; /*  link beacon status */  	struct bfa_fcport_trunk_s trunk;  	u16		fcoe_vlan; +	struct bfa_mem_dma_s	fcport_dma; +	bfa_boolean_t		stats_dma_ready; +	struct bfa_bbcr_attr_s	bbcr_attr; +	enum bfa_fec_state_s	fec_state;  };  #define BFA_FCPORT_MOD(__bfa)	(&(__bfa)->modules.fcport) +#define BFA_MEM_FCPORT_DMA(__bfa) (&(BFA_FCPORT_MOD(__bfa)->fcport_dma))  /*   * protected functions @@ -487,6 +536,7 @@ enum bfa_port_speed bfa_fcport_get_speed(struct bfa_s *bfa);  bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,  				     enum bfa_port_topology topo);  enum bfa_port_topology bfa_fcport_get_topology(struct bfa_s *bfa); +enum bfa_port_topology bfa_fcport_get_cfg_topology(struct bfa_s *bfa);  bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);  bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);  u8 bfa_fcport_get_myalpa(struct bfa_s *bfa); @@ -500,79 +550,78 @@ void bfa_fcport_event_register(struct bfa_s *bfa,  			void (*event_cbfn) (void *cbarg,  			enum bfa_port_linkstate event), void *event_cbarg);  bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa); -void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off); -void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off); -bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, -					  enum bfa_port_speed speed); +bfa_boolean_t bfa_fcport_is_dport(struct bfa_s *bfa); +bfa_boolean_t bfa_fcport_is_ddport(struct bfa_s *bfa); +bfa_status_t bfa_fcport_set_qos_bw(struct bfa_s *bfa, +				   struct bfa_qos_bw_s *qos_bw);  enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);  void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit); -void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status); -void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon, -		       bfa_boolean_t link_e2e_beacon); -void bfa_fcport_qos_get_attr(struct bfa_s *bfa, -			     struct bfa_qos_attr_s *qos_attr); -void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa, -				struct bfa_qos_vc_attr_s *qos_vc_attr); -bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa, -				      union bfa_fcport_stats_u *stats, -				      bfa_cb_port_t cbfn, void *cbarg); -bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, -					void *cbarg); -bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, -				       union bfa_fcport_stats_u *stats, -				       bfa_cb_port_t cbfn, void *cbarg); -bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, -					 void *cbarg);  bfa_boolean_t     bfa_fcport_is_ratelim(struct bfa_s *bfa); +void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon, +			bfa_boolean_t link_e2e_beacon);  bfa_boolean_t	bfa_fcport_is_linkup(struct bfa_s *bfa);  bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, -				  union bfa_fcport_stats_u *stats, -				  bfa_cb_port_t cbfn, void *cbarg); -bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, -				    void *cbarg); +			struct bfa_cb_pending_q_s *cb); +bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, +			struct bfa_cb_pending_q_s *cb);  bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); +bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa); +void bfa_fcport_dportenable(struct bfa_s *bfa); +void bfa_fcport_dportdisable(struct bfa_s *bfa); +bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa); +void bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state); +bfa_status_t bfa_fcport_cfg_bbcr(struct bfa_s *bfa, +			bfa_boolean_t on_off, u8 bb_scn); +bfa_status_t bfa_fcport_get_bbcr_attr(struct bfa_s *bfa, +			struct bfa_bbcr_attr_s *bbcr_attr);  /*   * bfa rport API functions   */  struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv); -void bfa_rport_delete(struct bfa_rport_s *rport);  void bfa_rport_online(struct bfa_rport_s *rport,  		      struct bfa_rport_info_s *rport_info); -void bfa_rport_offline(struct bfa_rport_s *rport);  void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed); -void bfa_rport_get_stats(struct bfa_rport_s *rport, -			 struct bfa_rport_hal_stats_s *stats); -void bfa_rport_clear_stats(struct bfa_rport_s *rport);  void bfa_cb_rport_online(void *rport);  void bfa_cb_rport_offline(void *rport);  void bfa_cb_rport_qos_scn_flowid(void *rport,  				 struct bfa_rport_qos_attr_s old_qos_attr,  				 struct bfa_rport_qos_attr_s new_qos_attr); +void bfa_cb_rport_scn_online(struct bfa_s *bfa); +void bfa_cb_rport_scn_offline(struct bfa_s *bfa); +void bfa_cb_rport_scn_no_dev(void *rp);  void bfa_cb_rport_qos_scn_prio(void *rport,  			       struct bfa_rport_qos_attr_s old_qos_attr,  			       struct bfa_rport_qos_attr_s new_qos_attr); -void bfa_rport_get_qos_attr(struct bfa_rport_s *rport, -			    struct bfa_rport_qos_attr_s *qos_attr); + +/* + *	Rport LUN masking related + */ +#define BFA_RPORT_TAG_INVALID	0xffff +#define BFA_LP_TAG_INVALID	0xff +void	bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp); +void	bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);  /*   * bfa fcxp API functions   */ -struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa, +struct bfa_fcxp_s *bfa_fcxp_req_rsp_alloc(void *bfad_fcxp, struct bfa_s *bfa,  				  int nreq_sgles, int nrsp_sgles,  				  bfa_fcxp_get_sgaddr_t get_req_sga,  				  bfa_fcxp_get_sglen_t get_req_sglen,  				  bfa_fcxp_get_sgaddr_t get_rsp_sga, -				  bfa_fcxp_get_sglen_t get_rsp_sglen); -void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe, +				  bfa_fcxp_get_sglen_t get_rsp_sglen, +				  bfa_boolean_t req); +void bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,  				bfa_fcxp_alloc_cbfn_t alloc_cbfn,  				void *cbarg, void *bfad_fcxp,  				int nreq_sgles, int nrsp_sgles,  				bfa_fcxp_get_sgaddr_t get_req_sga,  				bfa_fcxp_get_sglen_t get_req_sglen,  				bfa_fcxp_get_sgaddr_t get_rsp_sga, -				bfa_fcxp_get_sglen_t get_rsp_sglen); +				bfa_fcxp_get_sglen_t get_rsp_sglen, +				bfa_boolean_t req);  void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,  			    struct bfa_fcxp_wqe_s *wqe);  void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp); @@ -592,6 +641,7 @@ void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,  bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);  u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);  u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa); +void bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw);  static inline void *  bfa_uf_get_frmbuf(struct bfa_uf_s *uf) @@ -619,38 +669,95 @@ void bfa_uf_free(struct bfa_uf_s *uf);  u32 bfa_lps_get_max_vport(struct bfa_s *bfa);  struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);  void bfa_lps_delete(struct bfa_lps_s *lps); -void bfa_lps_discard(struct bfa_lps_s *lps);  void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,  		   u16 pdusz, wwn_t pwwn, wwn_t nwwn,  		   bfa_boolean_t auth_en);  void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,  		   wwn_t pwwn, wwn_t nwwn); -void bfa_lps_flogo(struct bfa_lps_s *lps);  void bfa_lps_fdisclogo(struct bfa_lps_s *lps); -u8 bfa_lps_get_tag(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps); -bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps); -u32 bfa_lps_get_pid(struct bfa_lps_s *lps); +void bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, u32 n2n_pid); +u8 bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag);  u32 bfa_lps_get_base_pid(struct bfa_s *bfa);  u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid); -u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps); -wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps); -wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps); -u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps); -u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps); -mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);  void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status); +void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);  void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);  void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);  void bfa_cb_lps_cvl_event(void *bfad, void *uarg); -void bfa_trunk_enable_cfg(struct bfa_s *bfa); -bfa_status_t bfa_trunk_enable(struct bfa_s *bfa); -bfa_status_t bfa_trunk_disable(struct bfa_s *bfa); -bfa_status_t bfa_trunk_get_attr(struct bfa_s *bfa, -		struct bfa_trunk_attr_s *attr); +/* FAA specific APIs */ +bfa_status_t bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr, +			bfa_cb_iocfc_t cbfn, void *cbarg); + +/* + *	FC DIAG data structure + */ +struct bfa_fcdiag_qtest_s { +	struct bfa_diag_qtest_result_s *result; +	bfa_cb_diag_t	cbfn; +	void		*cbarg; +	struct bfa_timer_s	timer; +	u32	status; +	u32	count; +	u8	lock; +	u8	queue; +	u8	all; +	u8	timer_active; +}; + +struct bfa_fcdiag_lb_s { +	bfa_cb_diag_t   cbfn; +	void            *cbarg; +	void            *result; +	bfa_boolean_t   lock; +	u32        status; +}; + +struct bfa_dport_s { +	struct bfa_s	*bfa;		/* Back pointer to BFA	*/ +	bfa_sm_t	sm;		/* finite state machine */ +	struct bfa_reqq_wait_s reqq_wait; +	bfa_cb_diag_t	cbfn; +	void		*cbarg; +	union bfi_diag_dport_msg_u i2hmsg; +	u8		test_state;	/* enum dport_test_state  */ +	u8		dynamic;	/* boolean_t  */ +	u8		rsvd[2]; +	u32		lpcnt; +	u32		payload;	/* user defined payload pattern */ +	wwn_t		rp_pwwn; +	wwn_t		rp_nwwn; +	struct bfa_diag_dport_result_s result; +}; + +struct bfa_fcdiag_s { +	struct bfa_s    *bfa;           /* Back pointer to BFA */ +	struct bfa_trc_mod_s   *trcmod; +	struct bfa_fcdiag_lb_s lb; +	struct bfa_fcdiag_qtest_s qtest; +	struct bfa_dport_s	dport; +}; + +#define BFA_FCDIAG_MOD(__bfa)	(&(__bfa)->modules.fcdiag) + +void	bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg); + +bfa_status_t	bfa_fcdiag_loopback(struct bfa_s *bfa, +				enum bfa_port_opmode opmode, +				enum bfa_port_speed speed, u32 lpcnt, u32 pat, +				struct bfa_diag_loopback_result_s *result, +				bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore, +			u32 queue, struct bfa_diag_qtest_result_s *result, +			bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_fcdiag_lb_is_running(struct bfa_s *bfa); +bfa_status_t	bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat, +					bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, +				  void *cbarg); +bfa_status_t	bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat, +				bfa_cb_diag_t cbfn, void *cbarg); +bfa_status_t	bfa_dport_show(struct bfa_s *bfa, +				struct bfa_diag_dport_result_s *result);  #endif /* __BFA_SVC_H__ */ diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 1f938974b84..7593b7c1d33 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -32,7 +32,6 @@  #include "bfad_drv.h"  #include "bfad_im.h"  #include "bfa_fcs.h" -#include "bfa_os_inc.h"  #include "bfa_defs.h"  #include "bfa.h" @@ -50,30 +49,42 @@ int		reqq_size, rspq_size, num_sgpgs;  int		rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;  int		bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;  int		bfa_io_max_sge = BFAD_IO_MAX_SGE; -int		log_level = 3; /* WARNING log level */ +int		bfa_log_level = 3; /* WARNING log level */  int		ioc_auto_recover = BFA_TRUE;  int		bfa_linkup_delay = -1;  int		fdmi_enable = BFA_TRUE;  int		pcie_max_read_reqsz;  int		bfa_debugfs_enable = 1;  int		msix_disable_cb = 0, msix_disable_ct = 0; +int		max_xfer_size = BFAD_MAX_SECTORS >> 1; +int		max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS; -u32	bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size; -u32     *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc; +/* Firmware releated */ +u32	bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size; +u32	*bfi_image_cb, *bfi_image_ct, *bfi_image_ct2; -const char *msix_name_ct[] = { +#define BFAD_FW_FILE_CB		"cbfw-3.2.3.0.bin" +#define BFAD_FW_FILE_CT		"ctfw-3.2.3.0.bin" +#define BFAD_FW_FILE_CT2	"ct2fw-3.2.3.0.bin" + +static u32 *bfad_load_fwimg(struct pci_dev *pdev); +static void bfad_free_fwimg(void); +static void bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image, +		u32 *bfi_image_size, char *fw_name); + +static const char *msix_name_ct[] = { +	"ctrl",  	"cpe0", "cpe1", "cpe2", "cpe3", -	"rme0", "rme1", "rme2", "rme3", -	"ctrl" }; +	"rme0", "rme1", "rme2", "rme3" }; -const char *msix_name_cb[] = { +static const char *msix_name_cb[] = {  	"cpe0", "cpe1", "cpe2", "cpe3",  	"rme0", "rme1", "rme2", "rme3",  	"eemc", "elpu0", "elpu1", "epss", "mlpu" }; -MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC); -MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA); -MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC); +MODULE_FIRMWARE(BFAD_FW_FILE_CB); +MODULE_FIRMWARE(BFAD_FW_FILE_CT); +MODULE_FIRMWARE(BFAD_FW_FILE_CT2);  module_param(os_name, charp, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(os_name, "OS name of the hba host machine"); @@ -108,8 +119,8 @@ module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32, Range[>0]");  module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255"); -module_param(log_level, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(log_level, "Driver log level, default=3, " +module_param(bfa_log_level, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(bfa_log_level, "Driver log level, default=3, "  				"Range[Critical:1|Error:2|Warning:3|Info:4]");  module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1, " @@ -135,6 +146,11 @@ MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "  module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"  		" Range[false:0|true:1]"); +module_param(max_xfer_size, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(max_xfer_size, "default=32MB," +		" Range[64k|128k|256k|512k|1024k|2048k]"); +module_param(max_rport_logins, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(max_rport_logins, "Max number of logins to initiator and target rports on a port (physical/logical), default=1024");  static void  bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event); @@ -188,6 +204,7 @@ static void  bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)  {  	unsigned long flags; +	bfa_status_t ret;  	bfa_trc(bfad, event); @@ -201,12 +218,12 @@ bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)  		if (bfad_setup_intr(bfad)) {  			printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",  					bfad->inst_no); -			bfa_sm_send_event(bfad, BFAD_E_INTR_INIT_FAILED); +			bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);  			break;  		}  		spin_lock_irqsave(&bfad->bfad_lock, flags); -		bfa_init(&bfad->bfa); +		bfa_iocfc_init(&bfad->bfa);  		spin_unlock_irqrestore(&bfad->bfad_lock, flags);  		/* Set up interrupt handler for each vectors */ @@ -223,8 +240,29 @@ bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)  		if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {  			bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);  		} else { +			printk(KERN_WARNING +				"bfa %s: bfa init failed\n", +				bfad->pci_name); +			spin_lock_irqsave(&bfad->bfad_lock, flags); +			bfa_fcs_init(&bfad->bfa_fcs); +			spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +			ret = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM); +			if (ret != BFA_STATUS_OK) { +				init_completion(&bfad->comp); + +				spin_lock_irqsave(&bfad->bfad_lock, flags); +				bfad->pport.flags |= BFAD_PORT_DELETE; +				bfa_fcs_exit(&bfad->bfa_fcs); +				spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +				wait_for_completion(&bfad->comp); + +				bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED); +				break; +			}  			bfad->bfad_flags |= BFAD_HAL_INIT_FAIL; -			bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED); +			bfa_sm_send_event(bfad, BFAD_E_HAL_INIT_FAILED);  		}  		break; @@ -254,12 +292,14 @@ bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)  		spin_unlock_irqrestore(&bfad->bfad_lock, flags);  		retval = bfad_start_ops(bfad); -		if (retval != BFA_STATUS_OK) +		if (retval != BFA_STATUS_OK) { +			bfa_sm_set_state(bfad, bfad_sm_failed);  			break; +		}  		bfa_sm_set_state(bfad, bfad_sm_operational);  		break; -	case BFAD_E_INTR_INIT_FAILED: +	case BFAD_E_INIT_FAILED:  		bfa_sm_set_state(bfad, bfad_sm_uninit);  		kthread_stop(bfad->bfad_tsk);  		spin_lock_irqsave(&bfad->bfad_lock, flags); @@ -267,7 +307,7 @@ bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)  		spin_unlock_irqrestore(&bfad->bfad_lock, flags);  		break; -	case BFAD_E_INIT_FAILED: +	case BFAD_E_HAL_INIT_FAILED:  		bfa_sm_set_state(bfad, bfad_sm_failed);  		break;  	default: @@ -291,13 +331,8 @@ bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event)  		break;  	case BFAD_E_STOP: -		if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE) -			bfad_uncfg_pport(bfad); -		if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE) { -			bfad_im_probe_undo(bfad); -			bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE; -		} -		bfad_stop(bfad); +		bfa_sm_set_state(bfad, bfad_sm_fcs_exit); +		bfa_sm_send_event(bfad, BFAD_E_FCS_EXIT_COMP);  		break;  	case BFAD_E_EXIT_COMP: @@ -440,23 +475,6 @@ bfa_fcb_lport_new(struct bfad_s *bfad, struct bfa_fcs_lport_s *port,  	return port_drv;  } -void -bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles, -		    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv) -{ -	struct bfad_port_s    *port_drv; - -	/* this will be only called from rmmod context */ -	if (vp_drv && !vp_drv->comp_del) { -		port_drv = (vp_drv) ? (&(vp_drv)->drv_port) : -				((vf_drv) ? (&(vf_drv)->base_port) : -				(&(bfad)->pport)); -		bfa_trc(bfad, roles); -		if (roles & BFA_LPORT_ROLE_FCP_IM) -			bfad_im_port_delete(bfad, port_drv); -	} -} -  /*   * FCS RPORT alloc callback, after successful PLOGI by FCS   */ @@ -489,7 +507,7 @@ bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)  	struct bfad_vport_s   *vport;  	int rc; -	vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL); +	vport = kzalloc(sizeof(struct bfad_vport_s), GFP_ATOMIC);  	if (!vport) {  		bfa_trc(bfad, 0);  		return; @@ -515,28 +533,26 @@ bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)  void  bfad_hal_mem_release(struct bfad_s *bfad)  { -	int		i;  	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo; -	struct bfa_mem_elem_s *meminfo_elem; - -	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) { -		meminfo_elem = &hal_meminfo->meminfo[i]; -		if (meminfo_elem->kva != NULL) { -			switch (meminfo_elem->mem_type) { -			case BFA_MEM_TYPE_KVA: -				vfree(meminfo_elem->kva); -				break; -			case BFA_MEM_TYPE_DMA: -				dma_free_coherent(&bfad->pcidev->dev, -					meminfo_elem->mem_len, -					meminfo_elem->kva, -					(dma_addr_t) meminfo_elem->dma); -				break; -			default: -				bfa_assert(0); -				break; -			} -		} +	struct bfa_mem_dma_s *dma_info, *dma_elem; +	struct bfa_mem_kva_s *kva_info, *kva_elem; +	struct list_head *dm_qe, *km_qe; + +	dma_info = &hal_meminfo->dma_info; +	kva_info = &hal_meminfo->kva_info; + +	/* Iterate through the KVA meminfo queue */ +	list_for_each(km_qe, &kva_info->qe) { +		kva_elem = (struct bfa_mem_kva_s *) km_qe; +		vfree(kva_elem->kva); +	} + +	/* Iterate through the DMA meminfo queue */ +	list_for_each(dm_qe, &dma_info->qe) { +		dma_elem = (struct bfa_mem_dma_s *) dm_qe; +		dma_free_coherent(&bfad->pcidev->dev, +				dma_elem->mem_len, dma_elem->kva, +				(dma_addr_t) dma_elem->dma);  	}  	memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s)); @@ -551,15 +567,15 @@ bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)  		bfa_cfg->fwcfg.num_ioim_reqs = num_ios;  	if (num_tms > 0)  		bfa_cfg->fwcfg.num_tskim_reqs = num_tms; -	if (num_fcxps > 0) +	if (num_fcxps > 0 && num_fcxps <= BFA_FCXP_MAX)  		bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps; -	if (num_ufbufs > 0) +	if (num_ufbufs > 0 && num_ufbufs <= BFA_UF_MAX)  		bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs;  	if (reqq_size > 0)  		bfa_cfg->drvcfg.num_reqq_elems = reqq_size;  	if (rspq_size > 0)  		bfa_cfg->drvcfg.num_rspq_elems = rspq_size; -	if (num_sgpgs > 0) +	if (num_sgpgs > 0 && num_sgpgs <= BFA_SGPG_MAX)  		bfa_cfg->drvcfg.num_sgpgs = num_sgpgs;  	/* @@ -579,85 +595,46 @@ bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)  bfa_status_t  bfad_hal_mem_alloc(struct bfad_s *bfad)  { -	int		i;  	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo; -	struct bfa_mem_elem_s *meminfo_elem; -	dma_addr_t	phys_addr; -	void	       *kva; +	struct bfa_mem_dma_s *dma_info, *dma_elem; +	struct bfa_mem_kva_s *kva_info, *kva_elem; +	struct list_head *dm_qe, *km_qe;  	bfa_status_t	rc = BFA_STATUS_OK; -	int retry_count = 0; -	int reset_value = 1; -	int min_num_sgpgs = 512; +	dma_addr_t	phys_addr;  	bfa_cfg_get_default(&bfad->ioc_cfg); - -retry:  	bfad_update_hal_cfg(&bfad->ioc_cfg);  	bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs; -	bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo); - -	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) { -		meminfo_elem = &hal_meminfo->meminfo[i]; -		switch (meminfo_elem->mem_type) { -		case BFA_MEM_TYPE_KVA: -			kva = vmalloc(meminfo_elem->mem_len); -			if (kva == NULL) { -				bfad_hal_mem_release(bfad); -				rc = BFA_STATUS_ENOMEM; -				goto ext; -			} -			memset(kva, 0, meminfo_elem->mem_len); -			meminfo_elem->kva = kva; -			break; -		case BFA_MEM_TYPE_DMA: -			kva = dma_alloc_coherent(&bfad->pcidev->dev, -				meminfo_elem->mem_len, &phys_addr, GFP_KERNEL); -			if (kva == NULL) { -				bfad_hal_mem_release(bfad); -				/* -				 * If we cannot allocate with default -				 * num_sgpages try with half the value. -				 */ -				if (num_sgpgs > min_num_sgpgs) { -					printk(KERN_INFO -					"bfad[%d]: memory allocation failed" -					" with num_sgpgs: %d\n", -						bfad->inst_no, num_sgpgs); -					nextLowerInt(&num_sgpgs); -					printk(KERN_INFO -					"bfad[%d]: trying to allocate memory" -					" with num_sgpgs: %d\n", -						bfad->inst_no, num_sgpgs); -					retry_count++; -					goto retry; -				} else { -					if (num_sgpgs_parm > 0) -						num_sgpgs = num_sgpgs_parm; -					else { -						reset_value = -							(1 << retry_count); -						num_sgpgs *= reset_value; -					} -					rc = BFA_STATUS_ENOMEM; -					goto ext; -				} -			} - -			if (num_sgpgs_parm > 0) -				num_sgpgs = num_sgpgs_parm; -			else { -				reset_value = (1 << retry_count); -				num_sgpgs *= reset_value; -			} - -			memset(kva, 0, meminfo_elem->mem_len); -			meminfo_elem->kva = kva; -			meminfo_elem->dma = phys_addr; -			break; -		default: -			break; +	bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo, &bfad->bfa); + +	dma_info = &hal_meminfo->dma_info; +	kva_info = &hal_meminfo->kva_info; + +	/* Iterate through the KVA meminfo queue */ +	list_for_each(km_qe, &kva_info->qe) { +		kva_elem = (struct bfa_mem_kva_s *) km_qe; +		kva_elem->kva = vmalloc(kva_elem->mem_len); +		if (kva_elem->kva == NULL) { +			bfad_hal_mem_release(bfad); +			rc = BFA_STATUS_ENOMEM; +			goto ext; +		} +		memset(kva_elem->kva, 0, kva_elem->mem_len); +	} +	/* Iterate through the DMA meminfo queue */ +	list_for_each(dm_qe, &dma_info->qe) { +		dma_elem = (struct bfa_mem_dma_s *) dm_qe; +		dma_elem->kva = dma_alloc_coherent(&bfad->pcidev->dev, +						dma_elem->mem_len, +						&phys_addr, GFP_KERNEL); +		if (dma_elem->kva == NULL) { +			bfad_hal_mem_release(bfad); +			rc = BFA_STATUS_ENOMEM; +			goto ext;  		} +		dma_elem->dma = phys_addr; +		memset(dma_elem->kva, 0, dma_elem->mem_len);  	}  ext:  	return rc; @@ -699,6 +676,7 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id,  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	bfa_fcs_vport_start(&vport->fcs_vport); +	list_add_tail(&vport->list_entry, &bfad->vport_list);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags);  	return BFA_STATUS_OK; @@ -725,7 +703,7 @@ bfad_bfa_tmo(unsigned long data)  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	bfa_timer_tick(&bfad->bfa); +	bfa_timer_beat(&bfad->bfa.timer_mod);  	bfa_comp_deq(&bfad->bfa, &doneq);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -768,13 +746,20 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)  	pci_set_master(pdev); -	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) -		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { +	if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) || +	    (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)) { +		if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || +		   (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) {  			printk(KERN_ERR "pci_set_dma_mask fail %p\n", pdev);  			goto out_release_region;  		} +	} + +	/* Enable PCIE Advanced Error Recovery (AER) if kernel supports */ +	pci_enable_pcie_error_reporting(pdev);  	bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); +	bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2));  	if (bfad->pci_bar0_kva == NULL) {  		printk(KERN_ERR "Fail to map bar0\n"); @@ -785,6 +770,7 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)  	bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn);  	bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva;  	bfad->hal_pcidev.device_id = pdev->device; +	bfad->hal_pcidev.ssid = pdev->subsystem_device;  	bfad->pci_name = pci_name(pdev);  	bfad->pci_attr.vendor_id = pdev->vendor; @@ -796,52 +782,25 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)  	bfad->pcidev = pdev;  	/* Adjust PCIe Maximum Read Request Size */ -	if (pcie_max_read_reqsz > 0) { -		int pcie_cap_reg; -		u16 pcie_dev_ctl; -		u16 mask = 0xffff; - -		switch (pcie_max_read_reqsz) { -		case 128: -			mask = 0x0; -			break; -		case 256: -			mask = 0x1000; -			break; -		case 512: -			mask = 0x2000; -			break; -		case 1024: -			mask = 0x3000; -			break; -		case 2048: -			mask = 0x4000; -			break; -		case 4096: -			mask = 0x5000; -			break; -		default: -			break; -		} - -		pcie_cap_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP); -		if (mask != 0xffff && pcie_cap_reg) { -			pcie_cap_reg += 0x08; -			pci_read_config_word(pdev, pcie_cap_reg, &pcie_dev_ctl); -			if ((pcie_dev_ctl & 0x7000) != mask) { -				printk(KERN_WARNING "BFA[%s]: " +	if (pci_is_pcie(pdev) && pcie_max_read_reqsz) { +		if (pcie_max_read_reqsz >= 128 && +		    pcie_max_read_reqsz <= 4096 && +		    is_power_of_2(pcie_max_read_reqsz)) { +			int max_rq = pcie_get_readrq(pdev); +			printk(KERN_WARNING "BFA[%s]: "  				"pcie_max_read_request_size is %d, " -				"reset to %d\n", bfad->pci_name, -				(1 << ((pcie_dev_ctl & 0x7000) >> 12)) << 7, +				"reset to %d\n", bfad->pci_name, max_rq,  				pcie_max_read_reqsz); - -				pcie_dev_ctl &= ~0x7000; -				pci_write_config_word(pdev, pcie_cap_reg, -						pcie_dev_ctl | mask); -			} +			pcie_set_readrq(pdev, pcie_max_read_reqsz); +		} else { +			printk(KERN_WARNING "BFA[%s]: invalid " +			       "pcie_max_read_request_size %d ignored\n", +			       bfad->pci_name, pcie_max_read_reqsz);  		}  	} +	pci_save_state(pdev); +  	return 0;  out_release_region: @@ -856,9 +815,11 @@ void  bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)  {  	pci_iounmap(pdev, bfad->pci_bar0_kva); +	pci_iounmap(pdev, bfad->pci_bar2_kva);  	pci_release_regions(pdev); +	/* Disable PCIE Advanced Error Recovery (AER) */ +	pci_disable_pcie_error_reporting(pdev);  	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL);  }  bfa_status_t @@ -879,11 +840,11 @@ bfad_drv_init(struct bfad_s *bfad)  		printk(KERN_WARNING  			"Not enough memory to attach all Brocade HBA ports, %s",  			"System may need more memory.\n"); -		goto out_hal_mem_alloc_failure; +		return BFA_STATUS_FAILED;  	} -	bfa_init_trc(&bfad->bfa, bfad->trcmod); -	bfa_init_plog(&bfad->bfa, &bfad->plog_buf); +	bfad->bfa.trcmod = bfad->trcmod; +	bfad->bfa.plog = &bfad->plog_buf;  	bfa_plog_init(&bfad->plog_buf);  	bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,  		     0, "Driver Attach"); @@ -893,17 +854,14 @@ bfad_drv_init(struct bfad_s *bfad)  	/* FCS INIT */  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod); +	bfad->bfa_fcs.trcmod = bfad->trcmod;  	bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); -	bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable); +	bfad->bfa_fcs.fdmi_enabled = fdmi_enable;  	spin_unlock_irqrestore(&bfad->bfad_lock, flags);  	bfad->bfad_flags |= BFAD_DRV_INIT_DONE;  	return BFA_STATUS_OK; - -out_hal_mem_alloc_failure: -	return BFA_STATUS_FAILED;  }  void @@ -913,7 +871,7 @@ bfad_drv_uninit(struct bfad_s *bfad)  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	init_completion(&bfad->comp); -	bfa_stop(&bfad->bfa); +	bfa_iocfc_stop(&bfad->bfa);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags);  	wait_for_completion(&bfad->comp); @@ -932,8 +890,9 @@ bfad_drv_start(struct bfad_s *bfad)  	unsigned long	flags;  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	bfa_start(&bfad->bfa); -	bfa_fcs_start(&bfad->bfa_fcs); +	bfa_iocfc_start(&bfad->bfa); +	bfa_fcs_pbc_vport_init(&bfad->bfa_fcs); +	bfa_fcs_fabric_modstart(&bfad->bfa_fcs);  	bfad->bfad_flags |= BFAD_HAL_START_DONE;  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -963,7 +922,7 @@ bfad_stop(struct bfad_s *bfad)  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	init_completion(&bfad->comp); -	bfa_stop(&bfad->bfa); +	bfa_iocfc_stop(&bfad->bfa);  	bfad->bfad_flags &= ~BFAD_HAL_START_DONE;  	spin_unlock_irqrestore(&bfad->bfad_lock, flags);  	wait_for_completion(&bfad->comp); @@ -992,10 +951,6 @@ bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role)  		bfad->pport.roles |= BFA_LPORT_ROLE_FCP_IM;  	} -	/* Setup the debugfs node for this scsi_host */ -	if (bfa_debugfs_enable) -		bfad_debugfs_init(&bfad->pport); -  	bfad->bfad_flags |= BFAD_CFG_PPORT_DONE;  out: @@ -1005,10 +960,6 @@ out:  void  bfad_uncfg_pport(struct bfad_s *bfad)  { -	/* Remove the debugfs node for this scsi_host */ -	kfree(bfad->regdata); -	bfad_debugfs_exit(&bfad->pport); -  	if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&  	    (bfad->pport.roles & BFA_LPORT_ROLE_FCP_IM)) {  		bfad_im_scsi_host_free(bfad, bfad->pport.im_port); @@ -1028,6 +979,12 @@ bfad_start_ops(struct bfad_s *bfad) {  	struct bfad_vport_s *vport, *vport_new;  	struct bfa_fcs_driver_info_s driver_info; +	/* Limit min/max. xfer size to [64k-32MB] */ +	if (max_xfer_size < BFAD_MIN_SECTORS >> 1) +		max_xfer_size = BFAD_MIN_SECTORS >> 1; +	if (max_xfer_size > BFAD_MAX_SECTORS >> 1) +		max_xfer_size = BFAD_MAX_SECTORS >> 1; +  	/* Fill the driver_info info to fcs*/  	memset(&driver_info, 0, sizeof(driver_info));  	strncpy(driver_info.version, BFAD_DRIVER_VERSION, @@ -1043,32 +1000,34 @@ bfad_start_ops(struct bfad_s *bfad) {  			sizeof(driver_info.host_os_patch) - 1);  	strncpy(driver_info.os_device_name, bfad->pci_name, -		sizeof(driver_info.os_device_name - 1)); +		sizeof(driver_info.os_device_name) - 1); -	/* FCS INIT */ +	/* FCS driver info init */  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info); -	bfa_fcs_init(&bfad->bfa_fcs); + +	if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE) +		bfa_fcs_update_cfg(&bfad->bfa_fcs); +	else +		bfa_fcs_init(&bfad->bfa_fcs); +  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); -	retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM); -	if (retval != BFA_STATUS_OK) { -		if (bfa_sm_cmp_state(bfad, bfad_sm_initializing)) -			bfa_sm_set_state(bfad, bfad_sm_failed); -		bfad_stop(bfad); -		return BFA_STATUS_FAILED; +	if (!(bfad->bfad_flags & BFAD_CFG_PPORT_DONE)) { +		retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM); +		if (retval != BFA_STATUS_OK) +			return BFA_STATUS_FAILED;  	} +	/* Setup fc host fixed attribute if the lk supports */ +	bfad_fc_host_init(bfad->pport.im_port); +  	/* BFAD level FC4 IM specific resource allocation */  	retval = bfad_im_probe(bfad);  	if (retval != BFA_STATUS_OK) {  		printk(KERN_WARNING "bfad_im_probe failed\n");  		if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))  			bfa_sm_set_state(bfad, bfad_sm_failed); -		bfad_im_probe_undo(bfad); -		bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE; -		bfad_uncfg_pport(bfad); -		bfad_stop(bfad);  		return BFA_STATUS_FAILED;  	} else  		bfad->bfad_flags |= BFAD_FC4_PROBE_DONE; @@ -1102,17 +1061,17 @@ bfad_start_ops(struct bfad_s *bfad) {  	/*  	 * If bfa_linkup_delay is set to -1 default; try to retrive the -	 * value using the bfad_os_get_linkup_delay(); else use the +	 * value using the bfad_get_linkup_delay(); else use the  	 * passed in module param value as the bfa_linkup_delay.  	 */  	if (bfa_linkup_delay < 0) { -		bfa_linkup_delay = bfad_os_get_linkup_delay(bfad); -		bfad_os_rport_online_wait(bfad); +		bfa_linkup_delay = bfad_get_linkup_delay(bfad); +		bfad_rport_online_wait(bfad);  		bfa_linkup_delay = -1;  	} else -		bfad_os_rport_online_wait(bfad); +		bfad_rport_online_wait(bfad); -	BFA_LOG(KERN_INFO, bfad, log_level, "bfa device claimed\n"); +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "bfa device claimed\n");  	return BFA_STATUS_OK;  } @@ -1167,7 +1126,6 @@ bfad_intx(int irq, void *dev_id)  		spin_lock_irqsave(&bfad->bfad_lock, flags);  		bfa_comp_free(&bfad->bfa, &doneq);  		spin_unlock_irqrestore(&bfad->bfad_lock, flags); -		bfa_trc_fp(bfad, irq);  	}  	return IRQ_HANDLED; @@ -1230,8 +1188,8 @@ bfad_install_msix_handler(struct bfad_s *bfad)  	for (i = 0; i < bfad->nvec; i++) {  		sprintf(bfad->msix_tab[i].name, "bfa-%s-%s",  				bfad->pci_name, -				((bfa_asic_id_ct(bfad->hal_pcidev.device_id)) ? -				msix_name_ct[i] : msix_name_cb[i])); +				((bfa_asic_id_cb(bfad->hal_pcidev.device_id)) ? +				msix_name_cb[i] : msix_name_ct[i]));  		error = request_irq(bfad->msix_tab[i].msix.vector,  				    (irq_handler_t) bfad_msix, 0, @@ -1245,6 +1203,9 @@ bfad_install_msix_handler(struct bfad_s *bfad)  				free_irq(bfad->msix_tab[j].msix.vector,  						&bfad->msix_tab[j]); +			bfad->bfad_flags &= ~BFAD_MSIX_ON; +			pci_disable_msix(bfad->pcidev); +  			return 1;  		}  	} @@ -1262,6 +1223,7 @@ bfad_setup_intr(struct bfad_s *bfad)  	u32 mask = 0, i, num_bit = 0, max_bit = 0;  	struct msix_entry msix_entries[MAX_MSIX_ENTRY];  	struct pci_dev *pdev = bfad->pcidev; +	u16	reg;  	/* Call BFA to get the msix map for this PCI function.  */  	bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit); @@ -1269,27 +1231,45 @@ bfad_setup_intr(struct bfad_s *bfad)  	/* Set up the msix entry table */  	bfad_init_msix_entry(bfad, msix_entries, mask, max_bit); -	if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) || -	    (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) { +	if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) || +	   (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) {  		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);  		if (error) { +			/* In CT1 & CT2, try to allocate just one vector */ +			if (bfa_asic_id_ctc(pdev->device)) { +				printk(KERN_WARNING "bfa %s: trying one msix " +				       "vector failed to allocate %d[%d]\n", +				       bfad->pci_name, bfad->nvec, error); +				bfad->nvec = 1; +				error = pci_enable_msix(bfad->pcidev, +						msix_entries, bfad->nvec); +			} +  			/*  			 * Only error number of vector is available.  			 * We don't have a mechanism to map multiple  			 * interrupts into one vector, so even if we  			 * can try to request less vectors, we don't  			 * know how to associate interrupt events to -			 *  vectors. Linux doesn't dupicate vectors +			 *  vectors. Linux doesn't duplicate vectors  			 * in the MSIX table for this case.  			 */ +			if (error) { +				printk(KERN_WARNING "bfad%d: " +				       "pci_enable_msix failed (%d), " +				       "use line based.\n", +					bfad->inst_no, error); +				goto line_based; +			} +		} -			printk(KERN_WARNING "bfad%d: " -				"pci_enable_msix failed (%d)," -				" use line based.\n", bfad->inst_no, error); +		/* Disable INTX in MSI-X mode */ +		pci_read_config_word(pdev, PCI_COMMAND, ®); -			goto line_based; -		} +		if (!(reg & PCI_COMMAND_INTX_DISABLE)) +			pci_write_config_word(pdev, PCI_COMMAND, +				reg | PCI_COMMAND_INTX_DISABLE);  		/* Save the vectors */  		for (i = 0; i < bfad->nvec; i++) { @@ -1312,6 +1292,7 @@ line_based:  		/* Enable interrupt handler failed */  		return 1;  	} +	bfad->bfad_flags |= BFAD_INTX_ON;  	return error;  } @@ -1328,7 +1309,7 @@ bfad_remove_intr(struct bfad_s *bfad)  		pci_disable_msix(bfad->pcidev);  		bfad->bfad_flags &= ~BFAD_MSIX_ON; -	} else { +	} else if (bfad->bfad_flags & BFAD_INTX_ON) {  		free_irq(bfad->pcidev->irq, bfad);  	}  } @@ -1340,7 +1321,7 @@ int  bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)  {  	struct bfad_s	*bfad; -	int		error = -ENODEV, retval; +	int		error = -ENODEV, retval, i;  	/* For single port cards - only claim function 0 */  	if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) && @@ -1364,6 +1345,12 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)  	bfa_trc_init(bfad->trcmod);  	bfa_trc(bfad, bfad_inst); +	/* AEN INIT */ +	INIT_LIST_HEAD(&bfad->free_aen_q); +	INIT_LIST_HEAD(&bfad->active_aen_q); +	for (i = 0; i < BFA_AEN_MAX_ENTRY; i++) +		list_add_tail(&bfad->aen_list[i].qe, &bfad->free_aen_q); +  	if (!(bfad_load_fwimg(pdev))) {  		kfree(bfad->trcmod);  		goto out_alloc_trace_failure; @@ -1385,11 +1372,18 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)  	bfa_sm_set_state(bfad, bfad_sm_uninit);  	spin_lock_init(&bfad->bfad_lock); +	spin_lock_init(&bfad->bfad_aen_spinlock); +  	pci_set_drvdata(pdev, bfad);  	bfad->ref_count = 0;  	bfad->pport.bfad = bfad;  	INIT_LIST_HEAD(&bfad->pbc_vport_list); +	INIT_LIST_HEAD(&bfad->vport_list); + +	/* Setup the debugfs node for this bfad */ +	if (bfa_debugfs_enable) +		bfad_debugfs_init(&bfad->pport);  	retval = bfad_drv_init(bfad);  	if (retval != BFA_STATUS_OK) @@ -1403,9 +1397,11 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)  	return 0;  out_bfad_sm_failure: -	bfa_detach(&bfad->bfa);  	bfad_hal_mem_release(bfad);  out_drv_init_failure: +	/* Remove the debugfs node for this bfad */ +	kfree(bfad->regdata); +	bfad_debugfs_exit(&bfad->pport);  	mutex_lock(&bfad_mutex);  	bfad_inst--;  	list_del(&bfad->list_entry); @@ -1447,6 +1443,10 @@ bfad_pci_remove(struct pci_dev *pdev)  	spin_unlock_irqrestore(&bfad->bfad_lock, flags);  	bfad_hal_mem_release(bfad); +	/* Remove the debugfs node for this bfad */ +	kfree(bfad->regdata); +	bfad_debugfs_exit(&bfad->pport); +  	/* Cleaning the BFAD instance */  	mutex_lock(&bfad_mutex);  	bfad_inst--; @@ -1458,6 +1458,197 @@ bfad_pci_remove(struct pci_dev *pdev)  	kfree(bfad);  } +/* + * PCI Error Recovery entry, error detected. + */ +static pci_ers_result_t +bfad_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ +	struct bfad_s *bfad = pci_get_drvdata(pdev); +	unsigned long	flags; +	pci_ers_result_t ret = PCI_ERS_RESULT_NONE; + +	dev_printk(KERN_ERR, &pdev->dev, +		   "error detected state: %d - flags: 0x%x\n", +		   state, bfad->bfad_flags); + +	switch (state) { +	case pci_channel_io_normal: /* non-fatal error */ +		spin_lock_irqsave(&bfad->bfad_lock, flags); +		bfad->bfad_flags &= ~BFAD_EEH_BUSY; +		/* Suspend/fail all bfa operations */ +		bfa_ioc_suspend(&bfad->bfa.ioc); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		del_timer_sync(&bfad->hal_tmo); +		ret = PCI_ERS_RESULT_CAN_RECOVER; +		break; +	case pci_channel_io_frozen: /* fatal error */ +		init_completion(&bfad->comp); +		spin_lock_irqsave(&bfad->bfad_lock, flags); +		bfad->bfad_flags |= BFAD_EEH_BUSY; +		/* Suspend/fail all bfa operations */ +		bfa_ioc_suspend(&bfad->bfa.ioc); +		bfa_fcs_stop(&bfad->bfa_fcs); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		wait_for_completion(&bfad->comp); + +		bfad_remove_intr(bfad); +		del_timer_sync(&bfad->hal_tmo); +		pci_disable_device(pdev); +		ret = PCI_ERS_RESULT_NEED_RESET; +		break; +	case pci_channel_io_perm_failure: /* PCI Card is DEAD */ +		spin_lock_irqsave(&bfad->bfad_lock, flags); +		bfad->bfad_flags |= BFAD_EEH_BUSY | +				    BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE; +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +		/* If the error_detected handler is called with the reason +		 * pci_channel_io_perm_failure - it will subsequently call +		 * pci_remove() entry point to remove the pci device from the +		 * system - So defer the cleanup to pci_remove(); cleaning up +		 * here causes inconsistent state during pci_remove(). +		 */ +		ret = PCI_ERS_RESULT_DISCONNECT; +		break; +	default: +		WARN_ON(1); +	} + +	return ret; +} + +int +restart_bfa(struct bfad_s *bfad) +{ +	unsigned long flags; +	struct pci_dev *pdev = bfad->pcidev; + +	bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, +		   &bfad->meminfo, &bfad->hal_pcidev); + +	/* Enable Interrupt and wait bfa_init completion */ +	if (bfad_setup_intr(bfad)) { +		dev_printk(KERN_WARNING, &pdev->dev, +			   "%s: bfad_setup_intr failed\n", bfad->pci_name); +		bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED); +		return -1; +	} + +	init_completion(&bfad->comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	bfa_iocfc_init(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	/* Set up interrupt handler for each vectors */ +	if ((bfad->bfad_flags & BFAD_MSIX_ON) && +	    bfad_install_msix_handler(bfad)) +		dev_printk(KERN_WARNING, &pdev->dev, +			   "%s: install_msix failed.\n", bfad->pci_name); + +	bfad_init_timer(bfad); +	wait_for_completion(&bfad->comp); +	bfad_drv_start(bfad); + +	return 0; +} + +/* + * PCI Error Recovery entry, re-initialize the chip. + */ +static pci_ers_result_t +bfad_pci_slot_reset(struct pci_dev *pdev) +{ +	struct bfad_s *bfad = pci_get_drvdata(pdev); +	u8 byte; + +	dev_printk(KERN_ERR, &pdev->dev, +		   "bfad_pci_slot_reset flags: 0x%x\n", bfad->bfad_flags); + +	if (pci_enable_device(pdev)) { +		dev_printk(KERN_ERR, &pdev->dev, "Cannot re-enable " +			   "PCI device after reset.\n"); +		return PCI_ERS_RESULT_DISCONNECT; +	} + +	pci_restore_state(pdev); + +	/* +	 * Read some byte (e.g. DMA max. payload size which can't +	 * be 0xff any time) to make sure - we did not hit another PCI error +	 * in the middle of recovery. If we did, then declare permanent failure. +	 */ +	pci_read_config_byte(pdev, 0x68, &byte); +	if (byte == 0xff) { +		dev_printk(KERN_ERR, &pdev->dev, +			   "slot_reset failed ... got another PCI error !\n"); +		goto out_disable_device; +	} + +	pci_save_state(pdev); +	pci_set_master(pdev); + +	if (pci_set_dma_mask(bfad->pcidev, DMA_BIT_MASK(64)) != 0) +		if (pci_set_dma_mask(bfad->pcidev, DMA_BIT_MASK(32)) != 0) +			goto out_disable_device; + +	pci_cleanup_aer_uncorrect_error_status(pdev); + +	if (restart_bfa(bfad) == -1) +		goto out_disable_device; + +	pci_enable_pcie_error_reporting(pdev); +	dev_printk(KERN_WARNING, &pdev->dev, +		   "slot_reset completed  flags: 0x%x!\n", bfad->bfad_flags); + +	return PCI_ERS_RESULT_RECOVERED; + +out_disable_device: +	pci_disable_device(pdev); +	return PCI_ERS_RESULT_DISCONNECT; +} + +static pci_ers_result_t +bfad_pci_mmio_enabled(struct pci_dev *pdev) +{ +	unsigned long	flags; +	struct bfad_s *bfad = pci_get_drvdata(pdev); + +	dev_printk(KERN_INFO, &pdev->dev, "mmio_enabled\n"); + +	/* Fetch FW diagnostic information */ +	bfa_ioc_debug_save_ftrc(&bfad->bfa.ioc); + +	/* Cancel all pending IOs */ +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	init_completion(&bfad->comp); +	bfa_fcs_stop(&bfad->bfa_fcs); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	wait_for_completion(&bfad->comp); + +	bfad_remove_intr(bfad); +	del_timer_sync(&bfad->hal_tmo); +	pci_disable_device(pdev); + +	return PCI_ERS_RESULT_NEED_RESET; +} + +static void +bfad_pci_resume(struct pci_dev *pdev) +{ +	unsigned long	flags; +	struct bfad_s *bfad = pci_get_drvdata(pdev); + +	dev_printk(KERN_WARNING, &pdev->dev, "resume\n"); + +	/* wait until the link is online */ +	bfad_rport_online_wait(bfad); + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	bfad->bfad_flags &= ~BFAD_EEH_BUSY; +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +} +  struct pci_device_id bfad_id_table[] = {  	{  		.vendor = BFA_PCI_VENDOR_ID_BROCADE, @@ -1487,17 +1678,44 @@ struct pci_device_id bfad_id_table[] = {  		.class = (PCI_CLASS_SERIAL_FIBER << 8),  		.class_mask = ~0,  	}, +	{ +		.vendor = BFA_PCI_VENDOR_ID_BROCADE, +		.device = BFA_PCI_DEVICE_ID_CT2, +		.subvendor = PCI_ANY_ID, +		.subdevice = PCI_ANY_ID, +		.class = (PCI_CLASS_SERIAL_FIBER << 8), +		.class_mask = ~0, +	}, +	{ +		.vendor = BFA_PCI_VENDOR_ID_BROCADE, +		.device = BFA_PCI_DEVICE_ID_CT2_QUAD, +		.subvendor = PCI_ANY_ID, +		.subdevice = PCI_ANY_ID, +		.class = (PCI_CLASS_SERIAL_FIBER << 8), +		.class_mask = ~0, +	},  	{0, 0},  };  MODULE_DEVICE_TABLE(pci, bfad_id_table); +/* + * PCI error recovery handlers. + */ +static struct pci_error_handlers bfad_err_handler = { +	.error_detected = bfad_pci_error_detected, +	.slot_reset = bfad_pci_slot_reset, +	.mmio_enabled = bfad_pci_mmio_enabled, +	.resume = bfad_pci_resume, +}; +  static struct pci_driver bfad_pci_driver = {  	.name = BFAD_DRIVER_NAME,  	.id_table = bfad_id_table,  	.probe = bfad_pci_probe, -	.remove = __devexit_p(bfad_pci_remove), +	.remove = bfad_pci_remove, +	.err_handler = &bfad_err_handler,  };  /* @@ -1524,8 +1742,9 @@ bfad_init(void)  	if (strcmp(FCPI_NAME, " fcpim") == 0)  		supported_fc4s |= BFA_LPORT_ROLE_FCP_IM; -	bfa_ioc_auto_recover(ioc_auto_recover); +	bfa_auto_recover = ioc_auto_recover;  	bfa_fcs_rport_set_del_timeout(rport_del_timeout); +	bfa_fcs_rport_set_max_logins(max_rport_logins);  	error = pci_register_driver(&bfad_pci_driver);  	if (error) { @@ -1552,7 +1771,7 @@ bfad_exit(void)  }  /* Firmware handling */ -u32 * +static void  bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,  		u32 *bfi_image_size, char *fw_name)  { @@ -1560,44 +1779,55 @@ bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,  	if (request_firmware(&fw, fw_name, &pdev->dev)) {  		printk(KERN_ALERT "Can't locate firmware %s\n", fw_name); -		goto error; +		*bfi_image = NULL; +		goto out;  	}  	*bfi_image = vmalloc(fw->size);  	if (NULL == *bfi_image) {  		printk(KERN_ALERT "Fail to allocate buffer for fw image "  			"size=%x!\n", (u32) fw->size); -		goto error; +		goto out;  	}  	memcpy(*bfi_image, fw->data, fw->size);  	*bfi_image_size = fw->size/sizeof(u32); +out: +	release_firmware(fw); +} -	return *bfi_image; +static u32 * +bfad_load_fwimg(struct pci_dev *pdev) +{ +	if (bfa_asic_id_ct2(pdev->device)) { +		if (bfi_image_ct2_size == 0) +			bfad_read_firmware(pdev, &bfi_image_ct2, +				&bfi_image_ct2_size, BFAD_FW_FILE_CT2); +		return bfi_image_ct2; +	} else if (bfa_asic_id_ct(pdev->device)) { +		if (bfi_image_ct_size == 0) +			bfad_read_firmware(pdev, &bfi_image_ct, +				&bfi_image_ct_size, BFAD_FW_FILE_CT); +		return bfi_image_ct; +	} else if (bfa_asic_id_cb(pdev->device)) { +		if (bfi_image_cb_size == 0) +			bfad_read_firmware(pdev, &bfi_image_cb, +				&bfi_image_cb_size, BFAD_FW_FILE_CB); +		return bfi_image_cb; +	} -error:  	return NULL;  } -u32 * -bfad_get_firmware_buf(struct pci_dev *pdev) +static void +bfad_free_fwimg(void)  { -	if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) { -		if (bfi_image_ct_fc_size == 0) -			bfad_read_firmware(pdev, &bfi_image_ct_fc, -				&bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC); -		return bfi_image_ct_fc; -	} else if (pdev->device == BFA_PCI_DEVICE_ID_CT) { -		if (bfi_image_ct_cna_size == 0) -			bfad_read_firmware(pdev, &bfi_image_ct_cna, -				&bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA); -		return bfi_image_ct_cna; -	} else { -		if (bfi_image_cb_fc_size == 0) -			bfad_read_firmware(pdev, &bfi_image_cb_fc, -				&bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC); -		return bfi_image_cb_fc; -	} +	if (bfi_image_ct2_size && bfi_image_ct2) +		vfree(bfi_image_ct2); +	if (bfi_image_ct_size && bfi_image_ct) +		vfree(bfi_image_ct); +	if (bfi_image_cb_size && bfi_image_cb) +		vfree(bfi_image_cb);  }  module_init(bfad_init); diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index ed9fff440b5..40be670a1cb 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -25,7 +25,7 @@  /*   * FC transport template entry, get SCSI target port ID.   */ -void +static void  bfad_im_get_starget_port_id(struct scsi_target *starget)  {  	struct Scsi_Host *shost; @@ -40,7 +40,7 @@ bfad_im_get_starget_port_id(struct scsi_target *starget)  	bfad = im_port->bfad;  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	itnim = bfad_os_get_itnim(im_port, starget->id); +	itnim = bfad_get_itnim(im_port, starget->id);  	if (itnim)  		fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); @@ -51,7 +51,7 @@ bfad_im_get_starget_port_id(struct scsi_target *starget)  /*   * FC transport template entry, get SCSI target nwwn.   */ -void +static void  bfad_im_get_starget_node_name(struct scsi_target *starget)  {  	struct Scsi_Host *shost; @@ -66,7 +66,7 @@ bfad_im_get_starget_node_name(struct scsi_target *starget)  	bfad = im_port->bfad;  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	itnim = bfad_os_get_itnim(im_port, starget->id); +	itnim = bfad_get_itnim(im_port, starget->id);  	if (itnim)  		node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim); @@ -77,7 +77,7 @@ bfad_im_get_starget_node_name(struct scsi_target *starget)  /*   * FC transport template entry, get SCSI target pwwn.   */ -void +static void  bfad_im_get_starget_port_name(struct scsi_target *starget)  {  	struct Scsi_Host *shost; @@ -92,7 +92,7 @@ bfad_im_get_starget_port_name(struct scsi_target *starget)  	bfad = im_port->bfad;  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	itnim = bfad_os_get_itnim(im_port, starget->id); +	itnim = bfad_get_itnim(im_port, starget->id);  	if (itnim)  		port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); @@ -103,7 +103,7 @@ bfad_im_get_starget_port_name(struct scsi_target *starget)  /*   * FC transport template entry, get SCSI host port ID.   */ -void +static void  bfad_im_get_host_port_id(struct Scsi_Host *shost)  {  	struct bfad_im_port_s *im_port = @@ -111,7 +111,7 @@ bfad_im_get_host_port_id(struct Scsi_Host *shost)  	struct bfad_port_s    *port = im_port->port;  	fc_host_port_id(shost) = -			bfa_os_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port)); +			bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));  }  /* @@ -218,6 +218,9 @@ bfad_im_get_host_speed(struct Scsi_Host *shost)  	case BFA_PORT_SPEED_10GBPS:  		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;  		break; +	case BFA_PORT_SPEED_16GBPS: +		fc_host_speed(shost) = FC_PORTSPEED_16GBIT; +		break;  	case BFA_PORT_SPEED_8GBPS:  		fc_host_speed(shost) = FC_PORTSPEED_8GBIT;  		break; @@ -332,23 +335,10 @@ bfad_im_reset_stats(struct Scsi_Host *shost)  }  /* - * FC transport template entry, get rport loss timeout. - */ -static void -bfad_im_get_rport_loss_tmo(struct fc_rport *rport) -{ -	struct bfad_itnim_data_s *itnim_data = rport->dd_data; -	struct bfad_itnim_s   *itnim = itnim_data->itnim; -	struct bfad_s         *bfad = itnim->im->bfad; -	unsigned long   flags; - -	spin_lock_irqsave(&bfad->bfad_lock, flags); -	rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); -	spin_unlock_irqrestore(&bfad->bfad_lock, flags); -} - -/*   * FC transport template entry, set rport loss timeout. + * Update dev_loss_tmo based on the value pushed down by the stack + * In case it is lesser than path_tov of driver, set it to path_tov + 1 + * to ensure that the driver times out before the application   */  static void  bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) @@ -356,15 +346,11 @@ bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)  	struct bfad_itnim_data_s *itnim_data = rport->dd_data;  	struct bfad_itnim_s   *itnim = itnim_data->itnim;  	struct bfad_s         *bfad = itnim->im->bfad; -	unsigned long   flags; - -	if (timeout > 0) { -		spin_lock_irqsave(&bfad->bfad_lock, flags); -		bfa_fcpim_path_tov_set(&bfad->bfa, timeout); -		rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); -		spin_unlock_irqrestore(&bfad->bfad_lock, flags); -	} +	uint16_t path_tov = bfa_fcpim_path_tov_get(&bfad->bfa); +	rport->dev_loss_tmo = timeout; +	if (timeout < path_tov) +		rport->dev_loss_tmo = path_tov + 1;  }  static int @@ -423,6 +409,23 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)  		vshost = vport->drv_port.im_port->shost;  		fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn);  		fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn); +		fc_host_supported_classes(vshost) = FC_COS_CLASS3; + +		memset(fc_host_supported_fc4s(vshost), 0, +			sizeof(fc_host_supported_fc4s(vshost))); + +		/* For FCP type 0x08 */ +		if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM) +			fc_host_supported_fc4s(vshost)[2] = 1; + +		/* For fibre channel services type 0x20 */ +		fc_host_supported_fc4s(vshost)[7] = 1; + +		fc_host_supported_speeds(vshost) = +				bfad_im_supported_speeds(&bfad->bfa); +		fc_host_maxframe_size(vshost) = +				bfa_fcport_get_maxfrsize(&bfad->bfa); +  		fc_vport->dd_data = vport;  		vport->drv_port.im_port->fc_vport = fc_vport;  	} else if (rc == BFA_STATUS_INVALID_WWN) @@ -439,6 +442,43 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)  	return status;  } +int +bfad_im_issue_fc_host_lip(struct Scsi_Host *shost) +{ +	struct bfad_im_port_s *im_port = +			(struct bfad_im_port_s *) shost->hostdata[0]; +	struct bfad_s *bfad = im_port->bfad; +	struct bfad_hal_comp fcomp; +	unsigned long flags; +	uint32_t status; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	status = bfa_port_disable(&bfad->bfa.modules.port, +					bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (status != BFA_STATUS_OK) +		return -EIO; + +	wait_for_completion(&fcomp.comp); +	if (fcomp.status != BFA_STATUS_OK) +		return -EIO; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	status = bfa_port_enable(&bfad->bfa.modules.port, +					bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (status != BFA_STATUS_OK) +		return -EIO; + +	wait_for_completion(&fcomp.comp); +	if (fcomp.status != BFA_STATUS_OK) +		return -EIO; + +	return 0; +} +  static int  bfad_im_vport_delete(struct fc_vport *fc_vport)  { @@ -454,8 +494,12 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)  	unsigned long flags;  	struct completion fcomp; -	if (im_port->flags & BFAD_PORT_DELETE) -		goto free_scsi_host; +	if (im_port->flags & BFAD_PORT_DELETE) { +		bfad_scsi_host_free(bfad, im_port); +		list_del(&vport->list_entry); +		kfree(vport); +		return 0; +	}  	port = im_port->port; @@ -486,9 +530,8 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)  	wait_for_completion(vport->comp_del); -free_scsi_host: -	bfad_os_scsi_host_free(bfad, im_port); - +	bfad_scsi_host_free(bfad, im_port); +	list_del(&vport->list_entry);  	kfree(vport);  	return 0; @@ -527,6 +570,34 @@ bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable)  	return 0;  } +void +bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport) +{ +	struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data; +	struct bfad_im_port_s *im_port = +			(struct bfad_im_port_s *)vport->drv_port.im_port; +	struct bfad_s *bfad = im_port->bfad; +	struct Scsi_Host *vshost = vport->drv_port.im_port->shost; +	char *sym_name = fc_vport->symbolic_name; +	struct bfa_fcs_vport_s *fcs_vport; +	wwn_t	pwwn; +	unsigned long flags; + +	u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (fcs_vport == NULL) +		return; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (strlen(sym_name) > 0) +		bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +} +  struct fc_function_template bfad_im_fc_function_template = {  	/* Target dynamic attributes */ @@ -574,12 +645,14 @@ struct fc_function_template bfad_im_fc_function_template = {  	.show_rport_maxframe_size = 1,  	.show_rport_supported_classes = 1,  	.show_rport_dev_loss_tmo = 1, -	.get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,  	.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, - +	.issue_fc_host_lip = bfad_im_issue_fc_host_lip,  	.vport_create = bfad_im_vport_create,  	.vport_delete = bfad_im_vport_delete,  	.vport_disable = bfad_im_vport_disable, +	.set_vport_symbolic_name = bfad_im_vport_set_symbolic_name, +	.bsg_request = bfad_im_bsg_request, +	.bsg_timeout = bfad_im_bsg_timeout,  };  struct fc_function_template bfad_im_vport_fc_function_template = { @@ -629,7 +702,6 @@ struct fc_function_template bfad_im_vport_fc_function_template = {  	.show_rport_maxframe_size = 1,  	.show_rport_supported_classes = 1,  	.show_rport_dev_loss_tmo = 1, -	.get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,  	.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,  }; @@ -674,8 +746,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,  	struct bfad_s *bfad = im_port->bfad;  	char model[BFA_ADAPTER_MODEL_NAME_LEN];  	char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN]; +	int nports = 0;  	bfa_get_adapter_model(&bfad->bfa, model); +	nports = bfa_get_nports(&bfad->bfa);  	if (!strcmp(model, "Brocade-425"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,  			"Brocade 4Gbps PCIe dual port FC HBA"); @@ -684,10 +758,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,  			"Brocade 8Gbps PCIe dual port FC HBA");  	else if (!strcmp(model, "Brocade-42B"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, -			"HP 4Gbps PCIe dual port FC HBA"); +			"Brocade 4Gbps PCIe dual port FC HBA for HP");  	else if (!strcmp(model, "Brocade-82B"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, -			"HP 8Gbps PCIe dual port FC HBA"); +			"Brocade 8Gbps PCIe dual port FC HBA for HP");  	else if (!strcmp(model, "Brocade-1010"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,  			"Brocade 10Gbps single port CNA"); @@ -696,7 +770,7 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,  			"Brocade 10Gbps dual port CNA");  	else if (!strcmp(model, "Brocade-1007"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, -			"Brocade 10Gbps CNA"); +			"Brocade 10Gbps CNA for IBM Blade Center");  	else if (!strcmp(model, "Brocade-415"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,  			"Brocade 4Gbps PCIe single port FC HBA"); @@ -705,17 +779,37 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,  			"Brocade 8Gbps PCIe single port FC HBA");  	else if (!strcmp(model, "Brocade-41B"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, -			"HP 4Gbps PCIe single port FC HBA"); +			"Brocade 4Gbps PCIe single port FC HBA for HP");  	else if (!strcmp(model, "Brocade-81B"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, -			"HP 8Gbps PCIe single port FC HBA"); +			"Brocade 8Gbps PCIe single port FC HBA for HP");  	else if (!strcmp(model, "Brocade-804"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, -			"HP Bladesystem C-class 8Gbps FC HBA"); -	else if (!strcmp(model, "Brocade-902")) +			"Brocade 8Gbps FC HBA for HP Bladesystem C-class"); +	else if (!strcmp(model, "Brocade-1741"))  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, -			"Brocade 10Gbps CNA"); -	else +			"Brocade 10Gbps CNA for Dell M-Series Blade Servers"); +	else if (strstr(model, "Brocade-1860")) { +		if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc)) +			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, +				"Brocade 10Gbps single port CNA"); +		else if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) +			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, +				"Brocade 16Gbps PCIe single port FC HBA"); +		else if (nports == 2 && bfa_ioc_is_cna(&bfad->bfa.ioc)) +			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, +				"Brocade 10Gbps dual port CNA"); +		else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) +			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, +				"Brocade 16Gbps PCIe dual port FC HBA"); +	} else if (!strcmp(model, "Brocade-1867")) { +		if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) +			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, +				"Brocade 16Gbps PCIe single port FC HBA for IBM"); +		else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) +			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, +				"Brocade 16Gbps PCIe dual port FC HBA for IBM"); +	} else  		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,  			"Invalid Model"); @@ -832,15 +926,16 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,  	struct bfad_port_s    *port = im_port->port;  	struct bfad_s         *bfad = im_port->bfad;  	int        nrports = 2048; -	wwn_t          *rports = NULL; +	struct bfa_rport_qualifier_s *rports = NULL;  	unsigned long   flags; -	rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC); +	rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports, +			 GFP_ATOMIC);  	if (rports == NULL)  		return snprintf(buf, PAGE_SIZE, "Failed\n");  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports); +	bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags);  	kfree(rports); diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c new file mode 100644 index 00000000000..8994fb857ee --- /dev/null +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -0,0 +1,3595 @@ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + * + * Linux driver for Brocade Fibre Channel Host Bus Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#include <linux/uaccess.h> +#include "bfad_drv.h" +#include "bfad_im.h" +#include "bfad_bsg.h" + +BFA_TRC_FILE(LDRV, BSG); + +int +bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	int	rc = 0; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	/* If IOC is not in disabled state - return */ +	if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_OK; +		return rc; +	} + +	init_completion(&bfad->enable_comp); +	bfa_iocfc_enable(&bfad->bfa); +	iocmd->status = BFA_STATUS_OK; +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	wait_for_completion(&bfad->enable_comp); + +	return rc; +} + +int +bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	int	rc = 0; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_OK; +		return rc; +	} + +	if (bfad->disable_active) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		return -EBUSY; +	} + +	bfad->disable_active = BFA_TRUE; +	init_completion(&bfad->disable_comp); +	bfa_iocfc_disable(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	wait_for_completion(&bfad->disable_comp); +	bfad->disable_active = BFA_FALSE; +	iocmd->status = BFA_STATUS_OK; + +	return rc; +} + +static int +bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd) +{ +	int	i; +	struct bfa_bsg_ioc_info_s *iocmd = (struct bfa_bsg_ioc_info_s *)cmd; +	struct bfad_im_port_s	*im_port; +	struct bfa_port_attr_s	pattr; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	bfa_fcport_get_attr(&bfad->bfa, &pattr); +	iocmd->nwwn = pattr.nwwn; +	iocmd->pwwn = pattr.pwwn; +	iocmd->ioc_type = bfa_get_type(&bfad->bfa); +	iocmd->mac = bfa_get_mac(&bfad->bfa); +	iocmd->factory_mac = bfa_get_mfg_mac(&bfad->bfa); +	bfa_get_adapter_serial_num(&bfad->bfa, iocmd->serialnum); +	iocmd->factorynwwn = pattr.factorynwwn; +	iocmd->factorypwwn = pattr.factorypwwn; +	iocmd->bfad_num = bfad->inst_no; +	im_port = bfad->pport.im_port; +	iocmd->host = im_port->shost->host_no; +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	strcpy(iocmd->name, bfad->adapter_name); +	strcpy(iocmd->port_name, bfad->port_name); +	strcpy(iocmd->hwpath, bfad->pci_name); + +	/* set adapter hw path */ +	strcpy(iocmd->adapter_hwpath, bfad->pci_name); +	for (i = 0; iocmd->adapter_hwpath[i] != ':' && i < BFA_STRING_32; i++) +		; +	for (; iocmd->adapter_hwpath[++i] != ':' && i < BFA_STRING_32; ) +		; +	iocmd->adapter_hwpath[i] = '\0'; +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +static int +bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_ioc_attr_s *iocmd = (struct bfa_bsg_ioc_attr_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	bfa_ioc_get_attr(&bfad->bfa.ioc, &iocmd->ioc_attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	/* fill in driver attr info */ +	strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME); +	strncpy(iocmd->ioc_attr.driver_attr.driver_ver, +		BFAD_DRIVER_VERSION, BFA_VERSION_LEN); +	strcpy(iocmd->ioc_attr.driver_attr.fw_ver, +		iocmd->ioc_attr.adapter_attr.fw_ver); +	strcpy(iocmd->ioc_attr.driver_attr.bios_ver, +		iocmd->ioc_attr.adapter_attr.optrom_ver); + +	/* copy chip rev info first otherwise it will be overwritten */ +	memcpy(bfad->pci_attr.chip_rev, iocmd->ioc_attr.pci_attr.chip_rev, +		sizeof(bfad->pci_attr.chip_rev)); +	memcpy(&iocmd->ioc_attr.pci_attr, &bfad->pci_attr, +		sizeof(struct bfa_ioc_pci_attr_s)); + +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_ioc_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_ioc_stats_s *iocmd = (struct bfa_bsg_ioc_stats_s *)cmd; + +	bfa_ioc_get_stats(&bfad->bfa, &iocmd->ioc_stats); +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_ioc_get_fwstats(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_ioc_fwstats_s *iocmd = +			(struct bfa_bsg_ioc_fwstats_s *)cmd; +	void	*iocmd_bufptr; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_ioc_fwstats_s), +			sizeof(struct bfa_fw_stats_s)) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		goto out; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_ioc_fwstats_s); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ioc_fw_stats_get(&bfad->bfa.ioc, iocmd_bufptr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		goto out; +	} +out: +	bfa_trc(bfad, 0x6666); +	return 0; +} + +int +bfad_iocmd_ioc_reset_stats(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	unsigned long	flags; + +	if (v_cmd == IOCMD_IOC_RESET_STATS) { +		bfa_ioc_clear_stats(&bfad->bfa); +		iocmd->status = BFA_STATUS_OK; +	} else if (v_cmd == IOCMD_IOC_RESET_FWSTATS) { +		spin_lock_irqsave(&bfad->bfad_lock, flags); +		iocmd->status = bfa_ioc_fw_stats_clear(&bfad->bfa.ioc); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	} + +	return 0; +} + +int +bfad_iocmd_ioc_set_name(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ +	struct bfa_bsg_ioc_name_s *iocmd = (struct bfa_bsg_ioc_name_s *) cmd; + +	if (v_cmd == IOCMD_IOC_SET_ADAPTER_NAME) +		strcpy(bfad->adapter_name, iocmd->name); +	else if (v_cmd == IOCMD_IOC_SET_PORT_NAME) +		strcpy(bfad->port_name, iocmd->name); + +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_iocfc_attr_s *iocmd = (struct bfa_bsg_iocfc_attr_s *)cmd; + +	iocmd->status = BFA_STATUS_OK; +	bfa_iocfc_get_attr(&bfad->bfa, &iocmd->iocfc_attr); + +	return 0; +} + +int +bfad_iocmd_ioc_fw_sig_inv(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	unsigned long flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ioc_fwsig_invalidate(&bfad->bfa.ioc); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_iocfc_israttr_set(&bfad->bfa, &iocmd->attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_port_enable(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_port_enable(&bfad->bfa.modules.port, +					bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		return 0; +	} +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +	return 0; +} + +int +bfad_iocmd_port_disable(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_port_disable(&bfad->bfa.modules.port, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		return 0; +	} +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +	return 0; +} + +static int +bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_port_attr_s *iocmd = (struct bfa_bsg_port_attr_s *)cmd; +	struct bfa_lport_attr_s	port_attr; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	bfa_fcport_get_attr(&bfad->bfa, &iocmd->attr); +	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (iocmd->attr.topology != BFA_PORT_TOPOLOGY_NONE) +		iocmd->attr.pid = port_attr.pid; +	else +		iocmd->attr.pid = 0; + +	iocmd->attr.port_type = port_attr.port_type; +	iocmd->attr.loopback = port_attr.loopback; +	iocmd->attr.authfail = port_attr.authfail; +	strncpy(iocmd->attr.port_symname.symname, +		port_attr.port_cfg.sym_name.symname, +		sizeof(port_attr.port_cfg.sym_name.symname)); + +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_port_get_stats(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_port_stats_s *iocmd = (struct bfa_bsg_port_stats_s *)cmd; +	struct bfad_hal_comp fcomp; +	void	*iocmd_bufptr; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_port_stats_s), +			sizeof(union bfa_port_stats_u)) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_port_stats_s); + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_port_get_stats(&bfad->bfa.modules.port, +				iocmd_bufptr, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		goto out; +	} + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_port_reset_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_port_clear_stats(&bfad->bfa.modules.port, +					bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		return 0; +	} +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +	return 0; +} + +int +bfad_iocmd_set_port_cfg(struct bfad_s *bfad, void *iocmd, unsigned int v_cmd) +{ +	struct bfa_bsg_port_cfg_s *cmd = (struct bfa_bsg_port_cfg_s *)iocmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (v_cmd == IOCMD_PORT_CFG_TOPO) +		cmd->status = bfa_fcport_cfg_topology(&bfad->bfa, cmd->param); +	else if (v_cmd == IOCMD_PORT_CFG_SPEED) +		cmd->status = bfa_fcport_cfg_speed(&bfad->bfa, cmd->param); +	else if (v_cmd == IOCMD_PORT_CFG_ALPA) +		cmd->status = bfa_fcport_cfg_hardalpa(&bfad->bfa, cmd->param); +	else if (v_cmd == IOCMD_PORT_CLR_ALPA) +		cmd->status = bfa_fcport_clr_hardalpa(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_port_cfg_maxfrsize_s *iocmd = +				(struct bfa_bsg_port_cfg_maxfrsize_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcport_cfg_maxfrsize(&bfad->bfa, iocmd->maxfrsize); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_port_cfg_bbcr(struct bfad_s *bfad, unsigned int cmd, void *pcmd) +{ +	struct bfa_bsg_bbcr_enable_s *iocmd = +			(struct bfa_bsg_bbcr_enable_s *)pcmd; +	unsigned long flags; +	int rc; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (cmd == IOCMD_PORT_BBCR_ENABLE) +		rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_TRUE, iocmd->bb_scn); +	else if (cmd == IOCMD_PORT_BBCR_DISABLE) +		rc = bfa_fcport_cfg_bbcr(&bfad->bfa, BFA_FALSE, 0); +	else { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		return -EINVAL; +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	iocmd->status = rc; +	return 0; +} + +int +bfad_iocmd_port_get_bbcr_attr(struct bfad_s *bfad, void *pcmd) +{ +	struct bfa_bsg_bbcr_attr_s *iocmd = (struct bfa_bsg_bbcr_attr_s *) pcmd; +	unsigned long flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = +		bfa_fcport_get_bbcr_attr(&bfad->bfa, &iocmd->attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + + +static int +bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_fcs_lport_s	*fcs_port; +	struct bfa_bsg_lport_attr_s *iocmd = (struct bfa_bsg_lport_attr_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	bfa_fcs_lport_get_attr(fcs_port, &iocmd->port_attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_lport_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_bsg_lport_stats_s *iocmd = +			(struct bfa_bsg_lport_stats_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	bfa_fcs_lport_get_stats(fcs_port, &iocmd->port_stats); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_lport_reset_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_bsg_reset_stats_s *iocmd = +			(struct bfa_bsg_reset_stats_s *)cmd; +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa); +	struct list_head *qe, *qen; +	struct bfa_itnim_s *itnim; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->vpwwn); +	if (fcs_port == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	bfa_fcs_lport_clear_stats(fcs_port); +	/* clear IO stats from all active itnims */ +	list_for_each_safe(qe, qen, &fcpim->itnim_q) { +		itnim = (struct bfa_itnim_s *) qe; +		if (itnim->rport->rport_info.lp_tag != fcs_port->lp_tag) +			continue; +		bfa_itnim_clear_stats(itnim); +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_lport_get_iostats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_bsg_lport_iostats_s *iocmd = +			(struct bfa_bsg_lport_iostats_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	bfa_fcpim_port_iostats(&bfad->bfa, &iocmd->iostats, +			fcs_port->lp_tag); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_lport_get_rports_s *iocmd = +			(struct bfa_bsg_lport_get_rports_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	unsigned long	flags; +	void	*iocmd_bufptr; + +	if (iocmd->nrports == 0) +		return -EINVAL; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_lport_get_rports_s), +			sizeof(struct bfa_rport_qualifier_s) * iocmd->nrports) +			!= BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + +			sizeof(struct bfa_bsg_lport_get_rports_s); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		bfa_trc(bfad, 0); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	bfa_fcs_lport_get_rport_quals(fcs_port, +			(struct bfa_rport_qualifier_s *)iocmd_bufptr, +			&iocmd->nrports); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_rport_attr_s *iocmd = (struct bfa_bsg_rport_attr_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_rport_s *fcs_rport; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	if (iocmd->pid) +		fcs_rport = bfa_fcs_lport_get_rport_by_qualifier(fcs_port, +						iocmd->rpwwn, iocmd->pid); +	else +		fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn); +	if (fcs_rport == NULL) { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		goto out; +	} + +	bfa_fcs_rport_get_attr(fcs_rport, &iocmd->attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +static int +bfad_iocmd_rport_get_addr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_rport_scsi_addr_s *iocmd = +			(struct bfa_bsg_rport_scsi_addr_s *)cmd; +	struct bfa_fcs_lport_s	*fcs_port; +	struct bfa_fcs_itnim_s	*fcs_itnim; +	struct bfad_itnim_s	*drv_itnim; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	fcs_itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn); +	if (fcs_itnim == NULL) { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		goto out; +	} + +	drv_itnim = fcs_itnim->itnim_drv; + +	if (drv_itnim && drv_itnim->im_port) +		iocmd->host = drv_itnim->im_port->shost->host_no; +	else { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		goto out; +	} + +	iocmd->target = drv_itnim->scsi_tgt_id; +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	iocmd->bus = 0; +	iocmd->lun = 0; +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_rport_stats_s *iocmd = +			(struct bfa_bsg_rport_stats_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_rport_s *fcs_rport; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn); +	if (fcs_rport == NULL) { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		goto out; +	} + +	memcpy((void *)&iocmd->stats, (void *)&fcs_rport->stats, +		sizeof(struct bfa_rport_stats_s)); +	if (bfa_fcs_rport_get_halrport(fcs_rport)) { +		memcpy((void *)&iocmd->stats.hal_stats, +		       (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats), +			sizeof(struct bfa_rport_hal_stats_s)); +	} + +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_rport_clr_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_rport_reset_stats_s *iocmd = +				(struct bfa_bsg_rport_reset_stats_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_rport_s *fcs_rport; +	struct bfa_rport_s *rport; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn); +	if (fcs_rport == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		goto out; +	} + +	memset((char *)&fcs_rport->stats, 0, sizeof(struct bfa_rport_stats_s)); +	rport = bfa_fcs_rport_get_halrport(fcs_rport); +	if (rport) +		memset(&rport->stats, 0, sizeof(rport->stats)); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_rport_set_speed(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_rport_set_speed_s *iocmd = +				(struct bfa_bsg_rport_set_speed_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_rport_s *fcs_rport; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (fcs_port == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		goto out; +	} + +	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn); +	if (fcs_rport == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		goto out; +	} + +	fcs_rport->rpf.assigned_speed  = iocmd->speed; +	/* Set this speed in f/w only if the RPSC speed is not available */ +	if (fcs_rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN) +		if (fcs_rport->bfa_rport) +			bfa_rport_speed(fcs_rport->bfa_rport, iocmd->speed); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_vport_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_fcs_vport_s *fcs_vport; +	struct bfa_bsg_vport_attr_s *iocmd = (struct bfa_bsg_vport_attr_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->vpwwn); +	if (fcs_vport == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_VWWN; +		goto out; +	} + +	bfa_fcs_vport_get_attr(fcs_vport, &iocmd->vport_attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_vport_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_fcs_vport_s *fcs_vport; +	struct bfa_bsg_vport_stats_s *iocmd = +				(struct bfa_bsg_vport_stats_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->vpwwn); +	if (fcs_vport == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_VWWN; +		goto out; +	} + +	memcpy((void *)&iocmd->vport_stats, (void *)&fcs_vport->vport_stats, +		sizeof(struct bfa_vport_stats_s)); +	memcpy((void *)&iocmd->vport_stats.port_stats, +	       (void *)&fcs_vport->lport.stats, +		sizeof(struct bfa_lport_stats_s)); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_vport_clr_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_fcs_vport_s *fcs_vport; +	struct bfa_bsg_reset_stats_s *iocmd = +				(struct bfa_bsg_reset_stats_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->vpwwn); +	if (fcs_vport == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_VWWN; +		goto out; +	} + +	memset(&fcs_vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s)); +	memset(&fcs_vport->lport.stats, 0, sizeof(struct bfa_lport_stats_s)); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +static int +bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_fabric_get_lports_s *iocmd = +			(struct bfa_bsg_fabric_get_lports_s *)cmd; +	bfa_fcs_vf_t	*fcs_vf; +	uint32_t	nports = iocmd->nports; +	unsigned long	flags; +	void	*iocmd_bufptr; + +	if (nports == 0) { +		iocmd->status = BFA_STATUS_EINVAL; +		goto out; +	} + +	if (bfad_chk_iocmd_sz(payload_len, +		sizeof(struct bfa_bsg_fabric_get_lports_s), +		sizeof(wwn_t[iocmd->nports])) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		goto out; +	} + +	iocmd_bufptr = (char *)iocmd + +			sizeof(struct bfa_bsg_fabric_get_lports_s); + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id); +	if (fcs_vf == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_VFID; +		goto out; +	} +	bfa_fcs_vf_get_ports(fcs_vf, (wwn_t *)iocmd_bufptr, &nports); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	iocmd->nports = nports; +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_qos_set_bw(struct bfad_s *bfad, void *pcmd) +{ +	struct bfa_bsg_qos_bw_s *iocmd = (struct bfa_bsg_qos_bw_s *)pcmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcport_set_qos_bw(&bfad->bfa, &iocmd->qos_bw); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); + +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) && +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +		iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +	else { +		if (cmd == IOCMD_RATELIM_ENABLE) +			fcport->cfg.ratelimit = BFA_TRUE; +		else if (cmd == IOCMD_RATELIM_DISABLE) +			fcport->cfg.ratelimit = BFA_FALSE; + +		if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN) +			fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS; + +		iocmd->status = BFA_STATUS_OK; +	} + +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd) +{ +	struct bfa_bsg_trl_speed_s *iocmd = (struct bfa_bsg_trl_speed_s *)pcmd; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); + +	/* Auto and speeds greater than the supported speed, are invalid */ +	if ((iocmd->speed == BFA_PORT_SPEED_AUTO) || +	    (iocmd->speed > fcport->speed_sup)) { +		iocmd->status = BFA_STATUS_UNSUPP_SPEED; +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		return 0; +	} + +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) && +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +		iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +	else { +		fcport->cfg.trl_def_speed = iocmd->speed; +		iocmd->status = BFA_STATUS_OK; +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_cfg_fcpim(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcpim_s *iocmd = (struct bfa_bsg_fcpim_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	bfa_fcpim_path_tov_set(&bfad->bfa, iocmd->param); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcpim_modstats_s *iocmd = +			(struct bfa_bsg_fcpim_modstats_s *)cmd; +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa); +	struct list_head *qe, *qen; +	struct bfa_itnim_s *itnim; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	/* accumulate IO stats from itnim */ +	memset((void *)&iocmd->modstats, 0, sizeof(struct bfa_itnim_iostats_s)); +	list_for_each_safe(qe, qen, &fcpim->itnim_q) { +		itnim = (struct bfa_itnim_s *) qe; +		bfa_fcpim_add_stats(&iocmd->modstats, &(itnim->stats)); +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_fcpim_clr_modstats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcpim_modstatsclr_s *iocmd = +				(struct bfa_bsg_fcpim_modstatsclr_s *)cmd; +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa); +	struct list_head *qe, *qen; +	struct bfa_itnim_s *itnim; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	list_for_each_safe(qe, qen, &fcpim->itnim_q) { +		itnim = (struct bfa_itnim_s *) qe; +		bfa_itnim_clear_stats(itnim); +	} +	memset(&fcpim->del_itn_stats, 0, +		sizeof(struct bfa_fcpim_del_itn_stats_s)); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_fcpim_get_del_itn_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcpim_del_itn_stats_s *iocmd = +			(struct bfa_bsg_fcpim_del_itn_stats_s *)cmd; +	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa); +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	memcpy((void *)&iocmd->modstats, (void *)&fcpim->del_itn_stats, +		sizeof(struct bfa_fcpim_del_itn_stats_s)); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +static int +bfad_iocmd_itnim_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_itnim_attr_s *iocmd = (struct bfa_bsg_itnim_attr_s *)cmd; +	struct bfa_fcs_lport_s	*fcs_port; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->lpwwn); +	if (!fcs_port) +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +	else +		iocmd->status = bfa_fcs_itnim_attr_get(fcs_port, +					iocmd->rpwwn, &iocmd->attr); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +static int +bfad_iocmd_itnim_get_iostats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_itnim_iostats_s *iocmd = +			(struct bfa_bsg_itnim_iostats_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_itnim_s *itnim; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->lpwwn); +	if (!fcs_port) { +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		bfa_trc(bfad, 0); +	} else { +		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn); +		if (itnim == NULL) +			iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		else { +			iocmd->status = BFA_STATUS_OK; +			if (bfa_fcs_itnim_get_halitn(itnim)) +				memcpy((void *)&iocmd->iostats, (void *) +				&(bfa_fcs_itnim_get_halitn(itnim)->stats), +				       sizeof(struct bfa_itnim_iostats_s)); +		} +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +static int +bfad_iocmd_itnim_reset_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_rport_reset_stats_s *iocmd = +			(struct bfa_bsg_rport_reset_stats_s *)cmd; +	struct bfa_fcs_lport_s	*fcs_port; +	struct bfa_fcs_itnim_s	*itnim; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->pwwn); +	if (!fcs_port) +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +	else { +		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn); +		if (itnim == NULL) +			iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		else { +			iocmd->status = BFA_STATUS_OK; +			bfa_fcs_itnim_stats_clear(fcs_port, iocmd->rpwwn); +			bfa_itnim_clear_stats(bfa_fcs_itnim_get_halitn(itnim)); +		} +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +static int +bfad_iocmd_itnim_get_itnstats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_itnim_itnstats_s *iocmd = +			(struct bfa_bsg_itnim_itnstats_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_itnim_s *itnim; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->lpwwn); +	if (!fcs_port) { +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +		bfa_trc(bfad, 0); +	} else { +		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn); +		if (itnim == NULL) +			iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		else { +			iocmd->status = BFA_STATUS_OK; +			bfa_fcs_itnim_stats_get(fcs_port, iocmd->rpwwn, +					&iocmd->itnstats); +		} +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_fcport_enable(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	unsigned long flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcport_enable(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_fcport_disable(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	unsigned long flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcport_disable(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_ioc_get_pcifn_cfg(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_pcifn_cfg_s *iocmd = (struct bfa_bsg_pcifn_cfg_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ablk_query(&bfad->bfa.modules.ablk, +				&iocmd->pcifn_cfg, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ablk_pf_create(&bfad->bfa.modules.ablk, +				&iocmd->pcifn_id, iocmd->port, +				iocmd->pcifn_class, iocmd->bw_min, +				iocmd->bw_max, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_pcifn_delete(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ablk_pf_delete(&bfad->bfa.modules.ablk, +				iocmd->pcifn_id, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ablk_pf_update(&bfad->bfa.modules.ablk, +				iocmd->pcifn_id, iocmd->bw_min, +				iocmd->bw_max, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +	bfa_trc(bfad, iocmd->status); +out: +	return 0; +} + +int +bfad_iocmd_adapter_cfg_mode(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_adapter_cfg_mode_s *iocmd = +			(struct bfa_bsg_adapter_cfg_mode_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags = 0; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ablk_adapter_config(&bfad->bfa.modules.ablk, +				iocmd->cfg.mode, iocmd->cfg.max_pf, +				iocmd->cfg.max_vf, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_port_cfg_mode(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_port_cfg_mode_s *iocmd = +			(struct bfa_bsg_port_cfg_mode_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags = 0; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_ablk_port_config(&bfad->bfa.modules.ablk, +				iocmd->instance, iocmd->cfg.mode, +				iocmd->cfg.max_pf, iocmd->cfg.max_vf, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_ablk_optrom(struct bfad_s *bfad, unsigned int cmd, void *pcmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; +	struct bfad_hal_comp fcomp; +	unsigned long   flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (cmd == IOCMD_FLASH_ENABLE_OPTROM) +		iocmd->status = bfa_ablk_optrom_en(&bfad->bfa.modules.ablk, +					bfad_hcb_comp, &fcomp); +	else +		iocmd->status = bfa_ablk_optrom_dis(&bfad->bfa.modules.ablk, +					bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_faa_query(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_faa_attr_s *iocmd = (struct bfa_bsg_faa_attr_s *)cmd; +	struct bfad_hal_comp    fcomp; +	unsigned long   flags; + +	init_completion(&fcomp.comp); +	iocmd->status = BFA_STATUS_OK; +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_faa_query(&bfad->bfa, &iocmd->faa_attr, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (iocmd->status != BFA_STATUS_OK) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_cee_attr(struct bfad_s *bfad, void *cmd, unsigned int payload_len) +{ +	struct bfa_bsg_cee_attr_s *iocmd = +				(struct bfa_bsg_cee_attr_s *)cmd; +	void	*iocmd_bufptr; +	struct bfad_hal_comp	cee_comp; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_cee_attr_s), +			sizeof(struct bfa_cee_attr_s)) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_attr_s); + +	cee_comp.status = 0; +	init_completion(&cee_comp.comp); +	mutex_lock(&bfad_mutex); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_cee_get_attr(&bfad->bfa.modules.cee, iocmd_bufptr, +					 bfad_hcb_comp, &cee_comp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		mutex_unlock(&bfad_mutex); +		bfa_trc(bfad, 0x5555); +		goto out; +	} +	wait_for_completion(&cee_comp.comp); +	mutex_unlock(&bfad_mutex); +out: +	return 0; +} + +int +bfad_iocmd_cee_get_stats(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_cee_stats_s *iocmd = +				(struct bfa_bsg_cee_stats_s *)cmd; +	void	*iocmd_bufptr; +	struct bfad_hal_comp	cee_comp; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_cee_stats_s), +			sizeof(struct bfa_cee_stats_s)) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_stats_s); + +	cee_comp.status = 0; +	init_completion(&cee_comp.comp); +	mutex_lock(&bfad_mutex); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_cee_get_stats(&bfad->bfa.modules.cee, iocmd_bufptr, +					bfad_hcb_comp, &cee_comp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		mutex_unlock(&bfad_mutex); +		bfa_trc(bfad, 0x5555); +		goto out; +	} +	wait_for_completion(&cee_comp.comp); +	mutex_unlock(&bfad_mutex); +out: +	return 0; +} + +int +bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_cee_reset_stats(&bfad->bfa.modules.cee, NULL, NULL); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		bfa_trc(bfad, 0x5555); +	return 0; +} + +int +bfad_iocmd_sfp_media(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_sfp_media_s *iocmd = (struct bfa_bsg_sfp_media_s *)cmd; +	struct bfad_hal_comp	fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_sfp_media(BFA_SFP_MOD(&bfad->bfa), &iocmd->media, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_SFP_NOT_READY) +		goto out; + +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_sfp_speed(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_sfp_speed_s *iocmd = (struct bfa_bsg_sfp_speed_s *)cmd; +	struct bfad_hal_comp	fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_sfp_speed(BFA_SFP_MOD(&bfad->bfa), iocmd->speed, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_SFP_NOT_READY) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_flash_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_flash_attr_s *iocmd = +			(struct bfa_bsg_flash_attr_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_get_attr(BFA_FLASH(&bfad->bfa), &iocmd->attr, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_flash_erase_part(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_erase_part(BFA_FLASH(&bfad->bfa), iocmd->type, +				iocmd->instance, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_flash_update_part(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd; +	void	*iocmd_bufptr; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_flash_s), +			iocmd->bufsz) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s); + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa), +				iocmd->type, iocmd->instance, iocmd_bufptr, +				iocmd->bufsz, 0, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_flash_read_part(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd; +	struct bfad_hal_comp fcomp; +	void	*iocmd_bufptr; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_flash_s), +			iocmd->bufsz) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s); + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa), iocmd->type, +				iocmd->instance, iocmd_bufptr, iocmd->bufsz, 0, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_diag_temp(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_get_temp_s *iocmd = +			(struct bfa_bsg_diag_get_temp_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_diag_tsensor_query(BFA_DIAG_MOD(&bfad->bfa), +				&iocmd->result, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_diag_memtest(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_memtest_s *iocmd = +			(struct bfa_bsg_diag_memtest_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long   flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_diag_memtest(BFA_DIAG_MOD(&bfad->bfa), +				&iocmd->memtest, iocmd->pat, +				&iocmd->result, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_diag_loopback(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_loopback_s *iocmd = +			(struct bfa_bsg_diag_loopback_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long   flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcdiag_loopback(&bfad->bfa, iocmd->opmode, +				iocmd->speed, iocmd->lpcnt, iocmd->pat, +				&iocmd->result, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_diag_fwping(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_fwping_s *iocmd = +			(struct bfa_bsg_diag_fwping_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long   flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_diag_fwping(BFA_DIAG_MOD(&bfad->bfa), iocmd->cnt, +				iocmd->pattern, &iocmd->result, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	bfa_trc(bfad, 0x77771); +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_diag_queuetest(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_qtest_s *iocmd = (struct bfa_bsg_diag_qtest_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long   flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcdiag_queuetest(&bfad->bfa, iocmd->force, +				iocmd->queue, &iocmd->result, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_diag_sfp(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_sfp_show_s *iocmd = +			(struct bfa_bsg_sfp_show_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long   flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_sfp_show(BFA_SFP_MOD(&bfad->bfa), &iocmd->sfp, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +	bfa_trc(bfad, iocmd->status); +out: +	return 0; +} + +int +bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_led_s *iocmd = (struct bfa_bsg_diag_led_s *)cmd; +	unsigned long   flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_diag_ledtest(BFA_DIAG_MOD(&bfad->bfa), +				&iocmd->ledtest); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_beacon_s *iocmd = +			(struct bfa_bsg_diag_beacon_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_diag_beacon_port(BFA_DIAG_MOD(&bfad->bfa), +				iocmd->beacon, iocmd->link_e2e_beacon, +				iocmd->second); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_diag_lb_stat_s *iocmd = +			(struct bfa_bsg_diag_lb_stat_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcdiag_lb_is_running(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	bfa_trc(bfad, iocmd->status); + +	return 0; +} + +int +bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd) +{ +	struct bfa_bsg_dport_enable_s *iocmd = +				(struct bfa_bsg_dport_enable_s *)pcmd; +	unsigned long	flags; +	struct bfad_hal_comp fcomp; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_dport_enable(&bfad->bfa, iocmd->lpcnt, +					iocmd->pat, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		bfa_trc(bfad, iocmd->status); +	else { +		wait_for_completion(&fcomp.comp); +		iocmd->status = fcomp.status; +	} +	return 0; +} + +int +bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; +	unsigned long	flags; +	struct bfad_hal_comp fcomp; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_dport_disable(&bfad->bfa, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		bfa_trc(bfad, iocmd->status); +	else { +		wait_for_completion(&fcomp.comp); +		iocmd->status = fcomp.status; +	} +	return 0; +} + +int +bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd) +{ +	struct bfa_bsg_dport_enable_s *iocmd = +				(struct bfa_bsg_dport_enable_s *)pcmd; +	unsigned long   flags; +	struct bfad_hal_comp fcomp; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_dport_start(&bfad->bfa, iocmd->lpcnt, +					iocmd->pat, bfad_hcb_comp, +					&fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +	} else { +		wait_for_completion(&fcomp.comp); +		iocmd->status = fcomp.status; +	} + +	return 0; +} + +int +bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd) +{ +	struct bfa_bsg_diag_dport_show_s *iocmd = +				(struct bfa_bsg_diag_dport_show_s *)pcmd; +	unsigned long   flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_dport_show(&bfad->bfa, &iocmd->result); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + + +int +bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_phy_attr_s *iocmd = +			(struct bfa_bsg_phy_attr_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_phy_get_attr(BFA_PHY(&bfad->bfa), iocmd->instance, +				&iocmd->attr, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_phy_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_phy_stats_s *iocmd = +			(struct bfa_bsg_phy_stats_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_phy_get_stats(BFA_PHY(&bfad->bfa), iocmd->instance, +				&iocmd->stats, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_phy_read(struct bfad_s *bfad, void *cmd, unsigned int payload_len) +{ +	struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd; +	struct bfad_hal_comp fcomp; +	void	*iocmd_bufptr; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_phy_s), +			iocmd->bufsz) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s); +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_phy_read(BFA_PHY(&bfad->bfa), +				iocmd->instance, iocmd_bufptr, iocmd->bufsz, +				0, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +out: +	return 0; +} + +int +bfad_iocmd_vhba_query(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_vhba_attr_s *iocmd = +			(struct bfa_bsg_vhba_attr_s *)cmd; +	struct bfa_vhba_attr_s *attr = &iocmd->attr; +	unsigned long flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	attr->pwwn =  bfad->bfa.ioc.attr->pwwn; +	attr->nwwn =  bfad->bfa.ioc.attr->nwwn; +	attr->plog_enabled = (bfa_boolean_t)bfad->bfa.plog->plog_enabled; +	attr->io_profile = bfa_fcpim_get_io_profile(&bfad->bfa); +	attr->path_tov  = bfa_fcpim_path_tov_get(&bfad->bfa); +	iocmd->status = BFA_STATUS_OK; +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_phy_update(struct bfad_s *bfad, void *cmd, unsigned int payload_len) +{ +	struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd; +	void	*iocmd_bufptr; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	if (bfad_chk_iocmd_sz(payload_len, +			sizeof(struct bfa_bsg_phy_s), +			iocmd->bufsz) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s); +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_phy_update(BFA_PHY(&bfad->bfa), +				iocmd->instance, iocmd_bufptr, iocmd->bufsz, +				0, bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_porglog_get(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd; +	void *iocmd_bufptr; + +	if (iocmd->bufsz < sizeof(struct bfa_plog_s)) { +		bfa_trc(bfad, sizeof(struct bfa_plog_s)); +		iocmd->status = BFA_STATUS_EINVAL; +		goto out; +	} + +	iocmd->status = BFA_STATUS_OK; +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_debug_s); +	memcpy(iocmd_bufptr, (u8 *) &bfad->plog_buf, sizeof(struct bfa_plog_s)); +out: +	return 0; +} + +#define BFA_DEBUG_FW_CORE_CHUNK_SZ	0x4000U /* 16K chunks for FW dump */ +int +bfad_iocmd_debug_fw_core(struct bfad_s *bfad, void *cmd, +			unsigned int payload_len) +{ +	struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd; +	void	*iocmd_bufptr; +	unsigned long	flags; +	u32 offset; + +	if (bfad_chk_iocmd_sz(payload_len, sizeof(struct bfa_bsg_debug_s), +			BFA_DEBUG_FW_CORE_CHUNK_SZ) != BFA_STATUS_OK) { +		iocmd->status = BFA_STATUS_VERSION_FAIL; +		return 0; +	} + +	if (iocmd->bufsz < BFA_DEBUG_FW_CORE_CHUNK_SZ || +			!IS_ALIGNED(iocmd->bufsz, sizeof(u16)) || +			!IS_ALIGNED(iocmd->offset, sizeof(u32))) { +		bfa_trc(bfad, BFA_DEBUG_FW_CORE_CHUNK_SZ); +		iocmd->status = BFA_STATUS_EINVAL; +		goto out; +	} + +	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_debug_s); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	offset = iocmd->offset; +	iocmd->status = bfa_ioc_debug_fwcore(&bfad->bfa.ioc, iocmd_bufptr, +				&offset, &iocmd->bufsz); +	iocmd->offset = offset; +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +out: +	return 0; +} + +int +bfad_iocmd_debug_ctl(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	unsigned long	flags; + +	if (v_cmd == IOCMD_DEBUG_FW_STATE_CLR) { +		spin_lock_irqsave(&bfad->bfad_lock, flags); +		bfad->bfa.ioc.dbg_fwsave_once = BFA_TRUE; +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	} else if (v_cmd == IOCMD_DEBUG_PORTLOG_CLR) +		bfad->plog_buf.head = bfad->plog_buf.tail = 0; +	else if (v_cmd == IOCMD_DEBUG_START_DTRC) +		bfa_trc_init(bfad->trcmod); +	else if (v_cmd == IOCMD_DEBUG_STOP_DTRC) +		bfa_trc_stop(bfad->trcmod); + +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_porglog_ctl(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_portlogctl_s *iocmd = (struct bfa_bsg_portlogctl_s *)cmd; + +	if (iocmd->ctl == BFA_TRUE) +		bfad->plog_buf.plog_enabled = 1; +	else +		bfad->plog_buf.plog_enabled = 0; + +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_fcpim_cfg_profile(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ +	struct bfa_bsg_fcpim_profile_s *iocmd = +				(struct bfa_bsg_fcpim_profile_s *)cmd; +	struct timeval  tv; +	unsigned long	flags; + +	do_gettimeofday(&tv); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (v_cmd == IOCMD_FCPIM_PROFILE_ON) +		iocmd->status = bfa_fcpim_profile_on(&bfad->bfa, tv.tv_sec); +	else if (v_cmd == IOCMD_FCPIM_PROFILE_OFF) +		iocmd->status = bfa_fcpim_profile_off(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +static int +bfad_iocmd_itnim_get_ioprofile(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_itnim_ioprofile_s *iocmd = +				(struct bfa_bsg_itnim_ioprofile_s *)cmd; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_itnim_s *itnim; +	unsigned long   flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, +				iocmd->vf_id, iocmd->lpwwn); +	if (!fcs_port) +		iocmd->status = BFA_STATUS_UNKNOWN_LWWN; +	else { +		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn); +		if (itnim == NULL) +			iocmd->status = BFA_STATUS_UNKNOWN_RWWN; +		else +			iocmd->status = bfa_itnim_get_ioprofile( +						bfa_fcs_itnim_get_halitn(itnim), +						&iocmd->ioprofile); +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcport_stats_s *iocmd = +				(struct bfa_bsg_fcport_stats_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; +	struct bfa_cb_pending_q_s cb_qe; + +	init_completion(&fcomp.comp); +	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, +			   &fcomp, &iocmd->stats); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		goto out; +	} +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; +	struct bfa_cb_pending_q_s cb_qe; + +	init_completion(&fcomp.comp); +	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, &fcomp, NULL); + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		goto out; +	} +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_boot_cfg(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa), +			BFA_FLASH_PART_BOOT, bfad->bfa.ioc.port_id, +			&iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0, +			bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_boot_query(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa), +			BFA_FLASH_PART_BOOT, bfad->bfa.ioc.port_id, +			&iocmd->cfg, sizeof(struct bfa_boot_cfg_s), 0, +			bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_preboot_query(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_preboot_s *iocmd = (struct bfa_bsg_preboot_s *)cmd; +	struct bfi_iocfc_cfgrsp_s *cfgrsp = bfad->bfa.iocfc.cfgrsp; +	struct bfa_boot_pbc_s *pbcfg = &iocmd->cfg; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled; +	pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns; +	pbcfg->speed = cfgrsp->pbc_cfg.port_speed; +	memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun)); +	iocmd->status = BFA_STATUS_OK; +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_ethboot_cfg(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa), +				BFA_FLASH_PART_PXECFG, +				bfad->bfa.ioc.port_id, &iocmd->cfg, +				sizeof(struct bfa_ethboot_cfg_s), 0, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_ethboot_query(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa), +				BFA_FLASH_PART_PXECFG, +				bfad->bfa.ioc.port_id, &iocmd->cfg, +				sizeof(struct bfa_ethboot_cfg_s), 0, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) +		goto out; +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); +	struct bfa_fcport_trunk_s *trunk = &fcport->trunk; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); + +	if (bfa_fcport_is_dport(&bfad->bfa)) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		return BFA_STATUS_DPORT_ERR; +	} + +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) || +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +		iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +	else { +		if (v_cmd == IOCMD_TRUNK_ENABLE) { +			trunk->attr.state = BFA_TRUNK_OFFLINE; +			bfa_fcport_disable(&bfad->bfa); +			fcport->cfg.trunked = BFA_TRUE; +		} else if (v_cmd == IOCMD_TRUNK_DISABLE) { +			trunk->attr.state = BFA_TRUNK_DISABLED; +			bfa_fcport_disable(&bfad->bfa); +			fcport->cfg.trunked = BFA_FALSE; +		} + +		if (!bfa_fcport_is_disabled(&bfad->bfa)) +			bfa_fcport_enable(&bfad->bfa); + +		iocmd->status = BFA_STATUS_OK; +	} + +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_trunk_attr_s *iocmd = (struct bfa_bsg_trunk_attr_s *)cmd; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); +	struct bfa_fcport_trunk_s *trunk = &fcport->trunk; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) || +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +		iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +	else { +		memcpy((void *)&iocmd->attr, (void *)&trunk->attr, +			sizeof(struct bfa_trunk_attr_s)); +		iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa); +		iocmd->status = BFA_STATUS_OK; +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) { +		if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) && +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +			iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +		else { +			if (v_cmd == IOCMD_QOS_ENABLE) +				fcport->cfg.qos_enabled = BFA_TRUE; +			else if (v_cmd == IOCMD_QOS_DISABLE) { +				fcport->cfg.qos_enabled = BFA_FALSE; +				fcport->cfg.qos_bw.high = BFA_QOS_BW_HIGH; +				fcport->cfg.qos_bw.med = BFA_QOS_BW_MED; +				fcport->cfg.qos_bw.low = BFA_QOS_BW_LOW; +			} +		} +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_qos_attr_s *iocmd = (struct bfa_bsg_qos_attr_s *)cmd; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) && +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +		iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +	else { +		iocmd->attr.state = fcport->qos_attr.state; +		iocmd->attr.total_bb_cr = +			be32_to_cpu(fcport->qos_attr.total_bb_cr); +		iocmd->attr.qos_bw.high = fcport->cfg.qos_bw.high; +		iocmd->attr.qos_bw.med = fcport->cfg.qos_bw.med; +		iocmd->attr.qos_bw.low = fcport->cfg.qos_bw.low; +		iocmd->attr.qos_bw_op = fcport->qos_attr.qos_bw_op; +		iocmd->status = BFA_STATUS_OK; +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_qos_get_vc_attr(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_qos_vc_attr_s *iocmd = +				(struct bfa_bsg_qos_vc_attr_s *)cmd; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); +	struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr; +	unsigned long	flags; +	u32	i = 0; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->attr.total_vc_count = be16_to_cpu(bfa_vc_attr->total_vc_count); +	iocmd->attr.shared_credit  = be16_to_cpu(bfa_vc_attr->shared_credit); +	iocmd->attr.elp_opmode_flags  = +				be32_to_cpu(bfa_vc_attr->elp_opmode_flags); + +	/* Individual VC info */ +	while (i < iocmd->attr.total_vc_count) { +		iocmd->attr.vc_info[i].vc_credit = +				bfa_vc_attr->vc_info[i].vc_credit; +		iocmd->attr.vc_info[i].borrow_credit = +				bfa_vc_attr->vc_info[i].borrow_credit; +		iocmd->attr.vc_info[i].priority = +				bfa_vc_attr->vc_info[i].priority; +		i++; +	} +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	iocmd->status = BFA_STATUS_OK; +	return 0; +} + +int +bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcport_stats_s *iocmd = +				(struct bfa_bsg_fcport_stats_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; +	struct bfa_cb_pending_q_s cb_qe; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); + +	init_completion(&fcomp.comp); +	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, +			   &fcomp, &iocmd->stats); + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc)); +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) && +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +		iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +	else +		iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		goto out; +	} +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long	flags; +	struct bfa_cb_pending_q_s cb_qe; +	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa); + +	init_completion(&fcomp.comp); +	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, +			   &fcomp, NULL); + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc)); +	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) && +		(fcport->topology == BFA_PORT_TOPOLOGY_LOOP)) +		iocmd->status = BFA_STATUS_TOPOLOGY_LOOP; +	else +		iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status != BFA_STATUS_OK) { +		bfa_trc(bfad, iocmd->status); +		goto out; +	} +	wait_for_completion(&fcomp.comp); +	iocmd->status = fcomp.status; +out: +	return 0; +} + +int +bfad_iocmd_vf_get_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_vf_stats_s *iocmd = +			(struct bfa_bsg_vf_stats_s *)cmd; +	struct bfa_fcs_fabric_s	*fcs_vf; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id); +	if (fcs_vf == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_VFID; +		goto out; +	} +	memcpy((void *)&iocmd->stats, (void *)&fcs_vf->stats, +		sizeof(struct bfa_vf_stats_s)); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +int +bfad_iocmd_vf_clr_stats(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_vf_reset_stats_s *iocmd = +			(struct bfa_bsg_vf_reset_stats_s *)cmd; +	struct bfa_fcs_fabric_s	*fcs_vf; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id); +	if (fcs_vf == NULL) { +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		iocmd->status = BFA_STATUS_UNKNOWN_VFID; +		goto out; +	} +	memset((void *)&fcs_vf->stats, 0, sizeof(struct bfa_vf_stats_s)); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	iocmd->status = BFA_STATUS_OK; +out: +	return 0; +} + +/* Function to reset the LUN SCAN mode */ +static void +bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg) +{ +	struct bfad_im_port_s *pport_im = bfad->pport.im_port; +	struct bfad_vport_s *vport = NULL; + +	/* Set the scsi device LUN SCAN flags for base port */ +	bfad_reset_sdev_bflags(pport_im, lunmask_cfg); + +	/* Set the scsi device LUN SCAN flags for the vports */ +	list_for_each_entry(vport, &bfad->vport_list, list_entry) +		bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg); +} + +int +bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) +{ +	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) { +		iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE); +		/* Set the LUN Scanning mode to be Sequential scan */ +		if (iocmd->status == BFA_STATUS_OK) +			bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_TRUE); +	} else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) { +		iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE); +		/* Set the LUN Scanning mode to default REPORT_LUNS scan */ +		if (iocmd->status == BFA_STATUS_OK) +			bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_FALSE); +	} else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR) +		iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_fcpim_lunmask_query(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcpim_lunmask_query_s *iocmd = +			(struct bfa_bsg_fcpim_lunmask_query_s *)cmd; +	struct bfa_lunmask_cfg_s *lun_mask = &iocmd->lun_mask; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcpim_lunmask_query(&bfad->bfa, lun_mask); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd) +{ +	struct bfa_bsg_fcpim_lunmask_s *iocmd = +				(struct bfa_bsg_fcpim_lunmask_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	if (v_cmd == IOCMD_FCPIM_LUNMASK_ADD) +		iocmd->status = bfa_fcpim_lunmask_add(&bfad->bfa, iocmd->vf_id, +					&iocmd->pwwn, iocmd->rpwwn, iocmd->lun); +	else if (v_cmd == IOCMD_FCPIM_LUNMASK_DELETE) +		iocmd->status = bfa_fcpim_lunmask_delete(&bfad->bfa, +					iocmd->vf_id, &iocmd->pwwn, +					iocmd->rpwwn, iocmd->lun); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	return 0; +} + +int +bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcpim_throttle_s *iocmd = +			(struct bfa_bsg_fcpim_throttle_s *)cmd; +	unsigned long   flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcpim_throttle_get(&bfad->bfa, +				(void *)&iocmd->throttle); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fcpim_throttle_s *iocmd = +			(struct bfa_bsg_fcpim_throttle_s *)cmd; +	unsigned long	flags; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fcpim_throttle_set(&bfad->bfa, +				iocmd->throttle.cfg_value); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +int +bfad_iocmd_tfru_read(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_tfru_s *iocmd = +			(struct bfa_bsg_tfru_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags = 0; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_tfru_read(BFA_FRU(&bfad->bfa), +				&iocmd->data, iocmd->len, iocmd->offset, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status == BFA_STATUS_OK) { +		wait_for_completion(&fcomp.comp); +		iocmd->status = fcomp.status; +	} + +	return 0; +} + +int +bfad_iocmd_tfru_write(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_tfru_s *iocmd = +			(struct bfa_bsg_tfru_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags = 0; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_tfru_write(BFA_FRU(&bfad->bfa), +				&iocmd->data, iocmd->len, iocmd->offset, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status == BFA_STATUS_OK) { +		wait_for_completion(&fcomp.comp); +		iocmd->status = fcomp.status; +	} + +	return 0; +} + +int +bfad_iocmd_fruvpd_read(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fruvpd_s *iocmd = +			(struct bfa_bsg_fruvpd_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags = 0; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fruvpd_read(BFA_FRU(&bfad->bfa), +				&iocmd->data, iocmd->len, iocmd->offset, +				bfad_hcb_comp, &fcomp); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status == BFA_STATUS_OK) { +		wait_for_completion(&fcomp.comp); +		iocmd->status = fcomp.status; +	} + +	return 0; +} + +int +bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fruvpd_s *iocmd = +			(struct bfa_bsg_fruvpd_s *)cmd; +	struct bfad_hal_comp fcomp; +	unsigned long flags = 0; + +	init_completion(&fcomp.comp); +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fruvpd_update(BFA_FRU(&bfad->bfa), +				&iocmd->data, iocmd->len, iocmd->offset, +				bfad_hcb_comp, &fcomp, iocmd->trfr_cmpl); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); +	if (iocmd->status == BFA_STATUS_OK) { +		wait_for_completion(&fcomp.comp); +		iocmd->status = fcomp.status; +	} + +	return 0; +} + +int +bfad_iocmd_fruvpd_get_max_size(struct bfad_s *bfad, void *cmd) +{ +	struct bfa_bsg_fruvpd_max_size_s *iocmd = +			(struct bfa_bsg_fruvpd_max_size_s *)cmd; +	unsigned long flags = 0; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	iocmd->status = bfa_fruvpd_get_max_size(BFA_FRU(&bfad->bfa), +						&iocmd->max_size); +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return 0; +} + +static int +bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, +		unsigned int payload_len) +{ +	int rc = -EINVAL; + +	switch (cmd) { +	case IOCMD_IOC_ENABLE: +		rc = bfad_iocmd_ioc_enable(bfad, iocmd); +		break; +	case IOCMD_IOC_DISABLE: +		rc = bfad_iocmd_ioc_disable(bfad, iocmd); +		break; +	case IOCMD_IOC_GET_INFO: +		rc = bfad_iocmd_ioc_get_info(bfad, iocmd); +		break; +	case IOCMD_IOC_GET_ATTR: +		rc = bfad_iocmd_ioc_get_attr(bfad, iocmd); +		break; +	case IOCMD_IOC_GET_STATS: +		rc = bfad_iocmd_ioc_get_stats(bfad, iocmd); +		break; +	case IOCMD_IOC_GET_FWSTATS: +		rc = bfad_iocmd_ioc_get_fwstats(bfad, iocmd, payload_len); +		break; +	case IOCMD_IOC_RESET_STATS: +	case IOCMD_IOC_RESET_FWSTATS: +		rc = bfad_iocmd_ioc_reset_stats(bfad, iocmd, cmd); +		break; +	case IOCMD_IOC_SET_ADAPTER_NAME: +	case IOCMD_IOC_SET_PORT_NAME: +		rc = bfad_iocmd_ioc_set_name(bfad, iocmd, cmd); +		break; +	case IOCMD_IOCFC_GET_ATTR: +		rc = bfad_iocmd_iocfc_get_attr(bfad, iocmd); +		break; +	case IOCMD_IOCFC_SET_INTR: +		rc = bfad_iocmd_iocfc_set_intr(bfad, iocmd); +		break; +	case IOCMD_PORT_ENABLE: +		rc = bfad_iocmd_port_enable(bfad, iocmd); +		break; +	case IOCMD_PORT_DISABLE: +		rc = bfad_iocmd_port_disable(bfad, iocmd); +		break; +	case IOCMD_PORT_GET_ATTR: +		rc = bfad_iocmd_port_get_attr(bfad, iocmd); +		break; +	case IOCMD_PORT_GET_STATS: +		rc = bfad_iocmd_port_get_stats(bfad, iocmd, payload_len); +		break; +	case IOCMD_PORT_RESET_STATS: +		rc = bfad_iocmd_port_reset_stats(bfad, iocmd); +		break; +	case IOCMD_PORT_CFG_TOPO: +	case IOCMD_PORT_CFG_SPEED: +	case IOCMD_PORT_CFG_ALPA: +	case IOCMD_PORT_CLR_ALPA: +		rc = bfad_iocmd_set_port_cfg(bfad, iocmd, cmd); +		break; +	case IOCMD_PORT_CFG_MAXFRSZ: +		rc = bfad_iocmd_port_cfg_maxfrsize(bfad, iocmd); +		break; +	case IOCMD_PORT_BBCR_ENABLE: +	case IOCMD_PORT_BBCR_DISABLE: +		rc = bfad_iocmd_port_cfg_bbcr(bfad, cmd, iocmd); +		break; +	case IOCMD_PORT_BBCR_GET_ATTR: +		rc = bfad_iocmd_port_get_bbcr_attr(bfad, iocmd); +		break; +	case IOCMD_LPORT_GET_ATTR: +		rc = bfad_iocmd_lport_get_attr(bfad, iocmd); +		break; +	case IOCMD_LPORT_GET_STATS: +		rc = bfad_iocmd_lport_get_stats(bfad, iocmd); +		break; +	case IOCMD_LPORT_RESET_STATS: +		rc = bfad_iocmd_lport_reset_stats(bfad, iocmd); +		break; +	case IOCMD_LPORT_GET_IOSTATS: +		rc = bfad_iocmd_lport_get_iostats(bfad, iocmd); +		break; +	case IOCMD_LPORT_GET_RPORTS: +		rc = bfad_iocmd_lport_get_rports(bfad, iocmd, payload_len); +		break; +	case IOCMD_RPORT_GET_ATTR: +		rc = bfad_iocmd_rport_get_attr(bfad, iocmd); +		break; +	case IOCMD_RPORT_GET_ADDR: +		rc = bfad_iocmd_rport_get_addr(bfad, iocmd); +		break; +	case IOCMD_RPORT_GET_STATS: +		rc = bfad_iocmd_rport_get_stats(bfad, iocmd); +		break; +	case IOCMD_RPORT_RESET_STATS: +		rc = bfad_iocmd_rport_clr_stats(bfad, iocmd); +		break; +	case IOCMD_RPORT_SET_SPEED: +		rc = bfad_iocmd_rport_set_speed(bfad, iocmd); +		break; +	case IOCMD_VPORT_GET_ATTR: +		rc = bfad_iocmd_vport_get_attr(bfad, iocmd); +		break; +	case IOCMD_VPORT_GET_STATS: +		rc = bfad_iocmd_vport_get_stats(bfad, iocmd); +		break; +	case IOCMD_VPORT_RESET_STATS: +		rc = bfad_iocmd_vport_clr_stats(bfad, iocmd); +		break; +	case IOCMD_FABRIC_GET_LPORTS: +		rc = bfad_iocmd_fabric_get_lports(bfad, iocmd, payload_len); +		break; +	case IOCMD_RATELIM_ENABLE: +	case IOCMD_RATELIM_DISABLE: +		rc = bfad_iocmd_ratelim(bfad, cmd, iocmd); +		break; +	case IOCMD_RATELIM_DEF_SPEED: +		rc = bfad_iocmd_ratelim_speed(bfad, cmd, iocmd); +		break; +	case IOCMD_FCPIM_FAILOVER: +		rc = bfad_iocmd_cfg_fcpim(bfad, iocmd); +		break; +	case IOCMD_FCPIM_MODSTATS: +		rc = bfad_iocmd_fcpim_get_modstats(bfad, iocmd); +		break; +	case IOCMD_FCPIM_MODSTATSCLR: +		rc = bfad_iocmd_fcpim_clr_modstats(bfad, iocmd); +		break; +	case IOCMD_FCPIM_DEL_ITN_STATS: +		rc = bfad_iocmd_fcpim_get_del_itn_stats(bfad, iocmd); +		break; +	case IOCMD_ITNIM_GET_ATTR: +		rc = bfad_iocmd_itnim_get_attr(bfad, iocmd); +		break; +	case IOCMD_ITNIM_GET_IOSTATS: +		rc = bfad_iocmd_itnim_get_iostats(bfad, iocmd); +		break; +	case IOCMD_ITNIM_RESET_STATS: +		rc = bfad_iocmd_itnim_reset_stats(bfad, iocmd); +		break; +	case IOCMD_ITNIM_GET_ITNSTATS: +		rc = bfad_iocmd_itnim_get_itnstats(bfad, iocmd); +		break; +	case IOCMD_FCPORT_ENABLE: +		rc = bfad_iocmd_fcport_enable(bfad, iocmd); +		break; +	case IOCMD_FCPORT_DISABLE: +		rc = bfad_iocmd_fcport_disable(bfad, iocmd); +		break; +	case IOCMD_IOC_PCIFN_CFG: +		rc = bfad_iocmd_ioc_get_pcifn_cfg(bfad, iocmd); +		break; +	case IOCMD_IOC_FW_SIG_INV: +		rc = bfad_iocmd_ioc_fw_sig_inv(bfad, iocmd); +		break; +	case IOCMD_PCIFN_CREATE: +		rc = bfad_iocmd_pcifn_create(bfad, iocmd); +		break; +	case IOCMD_PCIFN_DELETE: +		rc = bfad_iocmd_pcifn_delete(bfad, iocmd); +		break; +	case IOCMD_PCIFN_BW: +		rc = bfad_iocmd_pcifn_bw(bfad, iocmd); +		break; +	case IOCMD_ADAPTER_CFG_MODE: +		rc = bfad_iocmd_adapter_cfg_mode(bfad, iocmd); +		break; +	case IOCMD_PORT_CFG_MODE: +		rc = bfad_iocmd_port_cfg_mode(bfad, iocmd); +		break; +	case IOCMD_FLASH_ENABLE_OPTROM: +	case IOCMD_FLASH_DISABLE_OPTROM: +		rc = bfad_iocmd_ablk_optrom(bfad, cmd, iocmd); +		break; +	case IOCMD_FAA_QUERY: +		rc = bfad_iocmd_faa_query(bfad, iocmd); +		break; +	case IOCMD_CEE_GET_ATTR: +		rc = bfad_iocmd_cee_attr(bfad, iocmd, payload_len); +		break; +	case IOCMD_CEE_GET_STATS: +		rc = bfad_iocmd_cee_get_stats(bfad, iocmd, payload_len); +		break; +	case IOCMD_CEE_RESET_STATS: +		rc = bfad_iocmd_cee_reset_stats(bfad, iocmd); +		break; +	case IOCMD_SFP_MEDIA: +		rc = bfad_iocmd_sfp_media(bfad, iocmd); +		 break; +	case IOCMD_SFP_SPEED: +		rc = bfad_iocmd_sfp_speed(bfad, iocmd); +		break; +	case IOCMD_FLASH_GET_ATTR: +		rc = bfad_iocmd_flash_get_attr(bfad, iocmd); +		break; +	case IOCMD_FLASH_ERASE_PART: +		rc = bfad_iocmd_flash_erase_part(bfad, iocmd); +		break; +	case IOCMD_FLASH_UPDATE_PART: +		rc = bfad_iocmd_flash_update_part(bfad, iocmd, payload_len); +		break; +	case IOCMD_FLASH_READ_PART: +		rc = bfad_iocmd_flash_read_part(bfad, iocmd, payload_len); +		break; +	case IOCMD_DIAG_TEMP: +		rc = bfad_iocmd_diag_temp(bfad, iocmd); +		break; +	case IOCMD_DIAG_MEMTEST: +		rc = bfad_iocmd_diag_memtest(bfad, iocmd); +		break; +	case IOCMD_DIAG_LOOPBACK: +		rc = bfad_iocmd_diag_loopback(bfad, iocmd); +		break; +	case IOCMD_DIAG_FWPING: +		rc = bfad_iocmd_diag_fwping(bfad, iocmd); +		break; +	case IOCMD_DIAG_QUEUETEST: +		rc = bfad_iocmd_diag_queuetest(bfad, iocmd); +		break; +	case IOCMD_DIAG_SFP: +		rc = bfad_iocmd_diag_sfp(bfad, iocmd); +		break; +	case IOCMD_DIAG_LED: +		rc = bfad_iocmd_diag_led(bfad, iocmd); +		break; +	case IOCMD_DIAG_BEACON_LPORT: +		rc = bfad_iocmd_diag_beacon_lport(bfad, iocmd); +		break; +	case IOCMD_DIAG_LB_STAT: +		rc = bfad_iocmd_diag_lb_stat(bfad, iocmd); +		break; +	case IOCMD_DIAG_DPORT_ENABLE: +		rc = bfad_iocmd_diag_dport_enable(bfad, iocmd); +		break; +	case IOCMD_DIAG_DPORT_DISABLE: +		rc = bfad_iocmd_diag_dport_disable(bfad, iocmd); +		break; +	case IOCMD_DIAG_DPORT_SHOW: +		rc = bfad_iocmd_diag_dport_show(bfad, iocmd); +		break; +	case IOCMD_DIAG_DPORT_START: +		rc = bfad_iocmd_diag_dport_start(bfad, iocmd); +		break; +	case IOCMD_PHY_GET_ATTR: +		rc = bfad_iocmd_phy_get_attr(bfad, iocmd); +		break; +	case IOCMD_PHY_GET_STATS: +		rc = bfad_iocmd_phy_get_stats(bfad, iocmd); +		break; +	case IOCMD_PHY_UPDATE_FW: +		rc = bfad_iocmd_phy_update(bfad, iocmd, payload_len); +		break; +	case IOCMD_PHY_READ_FW: +		rc = bfad_iocmd_phy_read(bfad, iocmd, payload_len); +		break; +	case IOCMD_VHBA_QUERY: +		rc = bfad_iocmd_vhba_query(bfad, iocmd); +		break; +	case IOCMD_DEBUG_PORTLOG: +		rc = bfad_iocmd_porglog_get(bfad, iocmd); +		break; +	case IOCMD_DEBUG_FW_CORE: +		rc = bfad_iocmd_debug_fw_core(bfad, iocmd, payload_len); +		break; +	case IOCMD_DEBUG_FW_STATE_CLR: +	case IOCMD_DEBUG_PORTLOG_CLR: +	case IOCMD_DEBUG_START_DTRC: +	case IOCMD_DEBUG_STOP_DTRC: +		rc = bfad_iocmd_debug_ctl(bfad, iocmd, cmd); +		break; +	case IOCMD_DEBUG_PORTLOG_CTL: +		rc = bfad_iocmd_porglog_ctl(bfad, iocmd); +		break; +	case IOCMD_FCPIM_PROFILE_ON: +	case IOCMD_FCPIM_PROFILE_OFF: +		rc = bfad_iocmd_fcpim_cfg_profile(bfad, iocmd, cmd); +		break; +	case IOCMD_ITNIM_GET_IOPROFILE: +		rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd); +		break; +	case IOCMD_FCPORT_GET_STATS: +		rc = bfad_iocmd_fcport_get_stats(bfad, iocmd); +		break; +	case IOCMD_FCPORT_RESET_STATS: +		rc = bfad_iocmd_fcport_reset_stats(bfad, iocmd); +		break; +	case IOCMD_BOOT_CFG: +		rc = bfad_iocmd_boot_cfg(bfad, iocmd); +		break; +	case IOCMD_BOOT_QUERY: +		rc = bfad_iocmd_boot_query(bfad, iocmd); +		break; +	case IOCMD_PREBOOT_QUERY: +		rc = bfad_iocmd_preboot_query(bfad, iocmd); +		break; +	case IOCMD_ETHBOOT_CFG: +		rc = bfad_iocmd_ethboot_cfg(bfad, iocmd); +		break; +	case IOCMD_ETHBOOT_QUERY: +		rc = bfad_iocmd_ethboot_query(bfad, iocmd); +		break; +	case IOCMD_TRUNK_ENABLE: +	case IOCMD_TRUNK_DISABLE: +		rc = bfad_iocmd_cfg_trunk(bfad, iocmd, cmd); +		break; +	case IOCMD_TRUNK_GET_ATTR: +		rc = bfad_iocmd_trunk_get_attr(bfad, iocmd); +		break; +	case IOCMD_QOS_ENABLE: +	case IOCMD_QOS_DISABLE: +		rc = bfad_iocmd_qos(bfad, iocmd, cmd); +		break; +	case IOCMD_QOS_GET_ATTR: +		rc = bfad_iocmd_qos_get_attr(bfad, iocmd); +		break; +	case IOCMD_QOS_GET_VC_ATTR: +		rc = bfad_iocmd_qos_get_vc_attr(bfad, iocmd); +		break; +	case IOCMD_QOS_GET_STATS: +		rc = bfad_iocmd_qos_get_stats(bfad, iocmd); +		break; +	case IOCMD_QOS_RESET_STATS: +		rc = bfad_iocmd_qos_reset_stats(bfad, iocmd); +		break; +	case IOCMD_QOS_SET_BW: +		rc = bfad_iocmd_qos_set_bw(bfad, iocmd); +		break; +	case IOCMD_VF_GET_STATS: +		rc = bfad_iocmd_vf_get_stats(bfad, iocmd); +		break; +	case IOCMD_VF_RESET_STATS: +		rc = bfad_iocmd_vf_clr_stats(bfad, iocmd); +		break; +	case IOCMD_FCPIM_LUNMASK_ENABLE: +	case IOCMD_FCPIM_LUNMASK_DISABLE: +	case IOCMD_FCPIM_LUNMASK_CLEAR: +		rc = bfad_iocmd_lunmask(bfad, iocmd, cmd); +		break; +	case IOCMD_FCPIM_LUNMASK_QUERY: +		rc = bfad_iocmd_fcpim_lunmask_query(bfad, iocmd); +		break; +	case IOCMD_FCPIM_LUNMASK_ADD: +	case IOCMD_FCPIM_LUNMASK_DELETE: +		rc = bfad_iocmd_fcpim_cfg_lunmask(bfad, iocmd, cmd); +		break; +	case IOCMD_FCPIM_THROTTLE_QUERY: +		rc = bfad_iocmd_fcpim_throttle_query(bfad, iocmd); +		break; +	case IOCMD_FCPIM_THROTTLE_SET: +		rc = bfad_iocmd_fcpim_throttle_set(bfad, iocmd); +		break; +	/* TFRU */ +	case IOCMD_TFRU_READ: +		rc = bfad_iocmd_tfru_read(bfad, iocmd); +		break; +	case IOCMD_TFRU_WRITE: +		rc = bfad_iocmd_tfru_write(bfad, iocmd); +		break; +	/* FRU */ +	case IOCMD_FRUVPD_READ: +		rc = bfad_iocmd_fruvpd_read(bfad, iocmd); +		break; +	case IOCMD_FRUVPD_UPDATE: +		rc = bfad_iocmd_fruvpd_update(bfad, iocmd); +		break; +	case IOCMD_FRUVPD_GET_MAX_SIZE: +		rc = bfad_iocmd_fruvpd_get_max_size(bfad, iocmd); +		break; +	default: +		rc = -EINVAL; +		break; +	} +	return rc; +} + +static int +bfad_im_bsg_vendor_request(struct fc_bsg_job *job) +{ +	uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0]; +	struct bfad_im_port_s *im_port = +			(struct bfad_im_port_s *) job->shost->hostdata[0]; +	struct bfad_s *bfad = im_port->bfad; +	struct request_queue *request_q = job->req->q; +	void *payload_kbuf; +	int rc = -EINVAL; + +	/* +	 * Set the BSG device request_queue size to 256 to support +	 * payloads larger than 512*1024K bytes. +	 */ +	blk_queue_max_segments(request_q, 256); + +	/* Allocate a temp buffer to hold the passed in user space command */ +	payload_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL); +	if (!payload_kbuf) { +		rc = -ENOMEM; +		goto out; +	} + +	/* Copy the sg_list passed in to a linear buffer: holds the cmnd data */ +	sg_copy_to_buffer(job->request_payload.sg_list, +			  job->request_payload.sg_cnt, payload_kbuf, +			  job->request_payload.payload_len); + +	/* Invoke IOCMD handler - to handle all the vendor command requests */ +	rc = bfad_iocmd_handler(bfad, vendor_cmd, payload_kbuf, +				job->request_payload.payload_len); +	if (rc != BFA_STATUS_OK) +		goto error; + +	/* Copy the response data to the job->reply_payload sg_list */ +	sg_copy_from_buffer(job->reply_payload.sg_list, +			    job->reply_payload.sg_cnt, +			    payload_kbuf, +			    job->reply_payload.payload_len); + +	/* free the command buffer */ +	kfree(payload_kbuf); + +	/* Fill the BSG job reply data */ +	job->reply_len = job->reply_payload.payload_len; +	job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; +	job->reply->result = rc; + +	job->job_done(job); +	return rc; +error: +	/* free the command buffer */ +	kfree(payload_kbuf); +out: +	job->reply->result = rc; +	job->reply_len = sizeof(uint32_t); +	job->reply->reply_payload_rcv_len = 0; +	return rc; +} + +/* FC passthru call backs */ +u64 +bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid) +{ +	struct bfad_fcxp	*drv_fcxp = bfad_fcxp; +	struct bfa_sge_s  *sge; +	u64	addr; + +	sge = drv_fcxp->req_sge + sgeid; +	addr = (u64)(size_t) sge->sg_addr; +	return addr; +} + +u32 +bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid) +{ +	struct bfad_fcxp	*drv_fcxp = bfad_fcxp; +	struct bfa_sge_s	*sge; + +	sge = drv_fcxp->req_sge + sgeid; +	return sge->sg_len; +} + +u64 +bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid) +{ +	struct bfad_fcxp	*drv_fcxp = bfad_fcxp; +	struct bfa_sge_s	*sge; +	u64	addr; + +	sge = drv_fcxp->rsp_sge + sgeid; +	addr = (u64)(size_t) sge->sg_addr; +	return addr; +} + +u32 +bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid) +{ +	struct bfad_fcxp	*drv_fcxp = bfad_fcxp; +	struct bfa_sge_s	*sge; + +	sge = drv_fcxp->rsp_sge + sgeid; +	return sge->sg_len; +} + +void +bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg, +		bfa_status_t req_status, u32 rsp_len, u32 resid_len, +		struct fchs_s *rsp_fchs) +{ +	struct bfad_fcxp *drv_fcxp = bfad_fcxp; + +	drv_fcxp->req_status = req_status; +	drv_fcxp->rsp_len = rsp_len; + +	/* bfa_fcxp will be automatically freed by BFA */ +	drv_fcxp->bfa_fcxp = NULL; +	complete(&drv_fcxp->comp); +} + +struct bfad_buf_info * +bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf, +		 uint32_t payload_len, uint32_t *num_sgles) +{ +	struct bfad_buf_info	*buf_base, *buf_info; +	struct bfa_sge_s	*sg_table; +	int sge_num = 1; + +	buf_base = kzalloc((sizeof(struct bfad_buf_info) + +			   sizeof(struct bfa_sge_s)) * sge_num, GFP_KERNEL); +	if (!buf_base) +		return NULL; + +	sg_table = (struct bfa_sge_s *) (((uint8_t *)buf_base) + +			(sizeof(struct bfad_buf_info) * sge_num)); + +	/* Allocate dma coherent memory */ +	buf_info = buf_base; +	buf_info->size = payload_len; +	buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size, +					&buf_info->phys, GFP_KERNEL); +	if (!buf_info->virt) +		goto out_free_mem; + +	/* copy the linear bsg buffer to buf_info */ +	memset(buf_info->virt, 0, buf_info->size); +	memcpy(buf_info->virt, payload_kbuf, buf_info->size); + +	/* +	 * Setup SG table +	 */ +	sg_table->sg_len = buf_info->size; +	sg_table->sg_addr = (void *)(size_t) buf_info->phys; + +	*num_sgles = sge_num; + +	return buf_base; + +out_free_mem: +	kfree(buf_base); +	return NULL; +} + +void +bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base, +		   uint32_t num_sgles) +{ +	int i; +	struct bfad_buf_info *buf_info = buf_base; + +	if (buf_base) { +		for (i = 0; i < num_sgles; buf_info++, i++) { +			if (buf_info->virt != NULL) +				dma_free_coherent(&bfad->pcidev->dev, +					buf_info->size, buf_info->virt, +					buf_info->phys); +		} +		kfree(buf_base); +	} +} + +int +bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp, +		   bfa_bsg_fcpt_t *bsg_fcpt) +{ +	struct bfa_fcxp_s *hal_fcxp; +	struct bfad_s	*bfad = drv_fcxp->port->bfad; +	unsigned long	flags; +	uint8_t	lp_tag; + +	spin_lock_irqsave(&bfad->bfad_lock, flags); + +	/* Allocate bfa_fcxp structure */ +	hal_fcxp = bfa_fcxp_req_rsp_alloc(drv_fcxp, &bfad->bfa, +				  drv_fcxp->num_req_sgles, +				  drv_fcxp->num_rsp_sgles, +				  bfad_fcxp_get_req_sgaddr_cb, +				  bfad_fcxp_get_req_sglen_cb, +				  bfad_fcxp_get_rsp_sgaddr_cb, +				  bfad_fcxp_get_rsp_sglen_cb, BFA_TRUE); +	if (!hal_fcxp) { +		bfa_trc(bfad, 0); +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		return BFA_STATUS_ENOMEM; +	} + +	drv_fcxp->bfa_fcxp = hal_fcxp; + +	lp_tag = bfa_lps_get_tag_from_pid(&bfad->bfa, bsg_fcpt->fchs.s_id); + +	bfa_fcxp_send(hal_fcxp, drv_fcxp->bfa_rport, bsg_fcpt->vf_id, lp_tag, +		      bsg_fcpt->cts, bsg_fcpt->cos, +		      job->request_payload.payload_len, +		      &bsg_fcpt->fchs, bfad_send_fcpt_cb, bfad, +		      job->reply_payload.payload_len, bsg_fcpt->tsecs); + +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	return BFA_STATUS_OK; +} + +int +bfad_im_bsg_els_ct_request(struct fc_bsg_job *job) +{ +	struct bfa_bsg_data *bsg_data; +	struct bfad_im_port_s *im_port = +			(struct bfad_im_port_s *) job->shost->hostdata[0]; +	struct bfad_s *bfad = im_port->bfad; +	bfa_bsg_fcpt_t *bsg_fcpt; +	struct bfad_fcxp    *drv_fcxp; +	struct bfa_fcs_lport_s *fcs_port; +	struct bfa_fcs_rport_s *fcs_rport; +	uint32_t command_type = job->request->msgcode; +	unsigned long flags; +	struct bfad_buf_info *rsp_buf_info; +	void *req_kbuf = NULL, *rsp_kbuf = NULL; +	int rc = -EINVAL; + +	job->reply_len  = sizeof(uint32_t);	/* Atleast uint32_t reply_len */ +	job->reply->reply_payload_rcv_len = 0; + +	/* Get the payload passed in from userspace */ +	bsg_data = (struct bfa_bsg_data *) (((char *)job->request) + +					sizeof(struct fc_bsg_request)); +	if (bsg_data == NULL) +		goto out; + +	/* +	 * Allocate buffer for bsg_fcpt and do a copy_from_user op for payload +	 * buffer of size bsg_data->payload_len +	 */ +	bsg_fcpt = kzalloc(bsg_data->payload_len, GFP_KERNEL); +	if (!bsg_fcpt) { +		rc = -ENOMEM; +		goto out; +	} + +	if (copy_from_user((uint8_t *)bsg_fcpt, +				(void *)(unsigned long)bsg_data->payload, +				bsg_data->payload_len)) { +		kfree(bsg_fcpt); +		rc = -EIO; +		goto out; +	} + +	drv_fcxp = kzalloc(sizeof(struct bfad_fcxp), GFP_KERNEL); +	if (drv_fcxp == NULL) { +		kfree(bsg_fcpt); +		rc = -ENOMEM; +		goto out; +	} + +	spin_lock_irqsave(&bfad->bfad_lock, flags); +	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, bsg_fcpt->vf_id, +					bsg_fcpt->lpwwn); +	if (fcs_port == NULL) { +		bsg_fcpt->status = BFA_STATUS_UNKNOWN_LWWN; +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		goto out_free_mem; +	} + +	/* Check if the port is online before sending FC Passthru cmd */ +	if (!bfa_fcs_lport_is_online(fcs_port)) { +		bsg_fcpt->status = BFA_STATUS_PORT_OFFLINE; +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		goto out_free_mem; +	} + +	drv_fcxp->port = fcs_port->bfad_port; + +	if (drv_fcxp->port->bfad == 0) +		drv_fcxp->port->bfad = bfad; + +	/* Fetch the bfa_rport - if nexus needed */ +	if (command_type == FC_BSG_HST_ELS_NOLOGIN || +	    command_type == FC_BSG_HST_CT) { +		/* BSG HST commands: no nexus needed */ +		drv_fcxp->bfa_rport = NULL; + +	} else if (command_type == FC_BSG_RPT_ELS || +		   command_type == FC_BSG_RPT_CT) { +		/* BSG RPT commands: nexus needed */ +		fcs_rport = bfa_fcs_lport_get_rport_by_pwwn(fcs_port, +							    bsg_fcpt->dpwwn); +		if (fcs_rport == NULL) { +			bsg_fcpt->status = BFA_STATUS_UNKNOWN_RWWN; +			spin_unlock_irqrestore(&bfad->bfad_lock, flags); +			goto out_free_mem; +		} + +		drv_fcxp->bfa_rport = fcs_rport->bfa_rport; + +	} else { /* Unknown BSG msgcode; return -EINVAL */ +		spin_unlock_irqrestore(&bfad->bfad_lock, flags); +		goto out_free_mem; +	} + +	spin_unlock_irqrestore(&bfad->bfad_lock, flags); + +	/* allocate memory for req / rsp buffers */ +	req_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL); +	if (!req_kbuf) { +		printk(KERN_INFO "bfa %s: fcpt request buffer alloc failed\n", +				bfad->pci_name); +		rc = -ENOMEM; +		goto out_free_mem; +	} + +	rsp_kbuf = kzalloc(job->reply_payload.payload_len, GFP_KERNEL); +	if (!rsp_kbuf) { +		printk(KERN_INFO "bfa %s: fcpt response buffer alloc failed\n", +				bfad->pci_name); +		rc = -ENOMEM; +		goto out_free_mem; +	} + +	/* map req sg - copy the sg_list passed in to the linear buffer */ +	sg_copy_to_buffer(job->request_payload.sg_list, +			  job->request_payload.sg_cnt, req_kbuf, +			  job->request_payload.payload_len); + +	drv_fcxp->reqbuf_info = bfad_fcxp_map_sg(bfad, req_kbuf, +					job->request_payload.payload_len, +					&drv_fcxp->num_req_sgles); +	if (!drv_fcxp->reqbuf_info) { +		printk(KERN_INFO "bfa %s: fcpt request fcxp_map_sg failed\n", +				bfad->pci_name); +		rc = -ENOMEM; +		goto out_free_mem; +	} + +	drv_fcxp->req_sge = (struct bfa_sge_s *) +			    (((uint8_t *)drv_fcxp->reqbuf_info) + +			    (sizeof(struct bfad_buf_info) * +					drv_fcxp->num_req_sgles)); + +	/* map rsp sg */ +	drv_fcxp->rspbuf_info = bfad_fcxp_map_sg(bfad, rsp_kbuf, +					job->reply_payload.payload_len, +					&drv_fcxp->num_rsp_sgles); +	if (!drv_fcxp->rspbuf_info) { +		printk(KERN_INFO "bfa %s: fcpt response fcxp_map_sg failed\n", +				bfad->pci_name); +		rc = -ENOMEM; +		goto out_free_mem; +	} + +	rsp_buf_info = (struct bfad_buf_info *)drv_fcxp->rspbuf_info; +	drv_fcxp->rsp_sge = (struct bfa_sge_s  *) +			    (((uint8_t *)drv_fcxp->rspbuf_info) + +			    (sizeof(struct bfad_buf_info) * +					drv_fcxp->num_rsp_sgles)); + +	/* fcxp send */ +	init_completion(&drv_fcxp->comp); +	rc = bfad_fcxp_bsg_send(job, drv_fcxp, bsg_fcpt); +	if (rc == BFA_STATUS_OK) { +		wait_for_completion(&drv_fcxp->comp); +		bsg_fcpt->status = drv_fcxp->req_status; +	} else { +		bsg_fcpt->status = rc; +		goto out_free_mem; +	} + +	/* fill the job->reply data */ +	if (drv_fcxp->req_status == BFA_STATUS_OK) { +		job->reply_len = drv_fcxp->rsp_len; +		job->reply->reply_payload_rcv_len = drv_fcxp->rsp_len; +		job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; +	} else { +		job->reply->reply_payload_rcv_len = +					sizeof(struct fc_bsg_ctels_reply); +		job->reply_len = sizeof(uint32_t); +		job->reply->reply_data.ctels_reply.status = +						FC_CTELS_STATUS_REJECT; +	} + +	/* Copy the response data to the reply_payload sg list */ +	sg_copy_from_buffer(job->reply_payload.sg_list, +			    job->reply_payload.sg_cnt, +			    (uint8_t *)rsp_buf_info->virt, +			    job->reply_payload.payload_len); + +out_free_mem: +	bfad_fcxp_free_mem(bfad, drv_fcxp->rspbuf_info, +			   drv_fcxp->num_rsp_sgles); +	bfad_fcxp_free_mem(bfad, drv_fcxp->reqbuf_info, +			   drv_fcxp->num_req_sgles); +	kfree(req_kbuf); +	kfree(rsp_kbuf); + +	/* Need a copy to user op */ +	if (copy_to_user((void *)(unsigned long)bsg_data->payload, +			(void *)bsg_fcpt, bsg_data->payload_len)) +		rc = -EIO; + +	kfree(bsg_fcpt); +	kfree(drv_fcxp); +out: +	job->reply->result = rc; + +	if (rc == BFA_STATUS_OK) +		job->job_done(job); + +	return rc; +} + +int +bfad_im_bsg_request(struct fc_bsg_job *job) +{ +	uint32_t rc = BFA_STATUS_OK; + +	switch (job->request->msgcode) { +	case FC_BSG_HST_VENDOR: +		/* Process BSG HST Vendor requests */ +		rc = bfad_im_bsg_vendor_request(job); +		break; +	case FC_BSG_HST_ELS_NOLOGIN: +	case FC_BSG_RPT_ELS: +	case FC_BSG_HST_CT: +	case FC_BSG_RPT_CT: +		/* Process BSG ELS/CT commands */ +		rc = bfad_im_bsg_els_ct_request(job); +		break; +	default: +		job->reply->result = rc = -EINVAL; +		job->reply->reply_payload_rcv_len = 0; +		break; +	} + +	return rc; +} + +int +bfad_im_bsg_timeout(struct fc_bsg_job *job) +{ +	/* Don't complete the BSG job request - return -EAGAIN +	 * to reset bsg job timeout : for ELS/CT pass thru we +	 * already have timer to track the request. +	 */ +	return -EAGAIN; +} diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h new file mode 100644 index 00000000000..90abef69158 --- /dev/null +++ b/drivers/scsi/bfa/bfad_bsg.h @@ -0,0 +1,836 @@ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + * + * Linux driver for Brocade Fibre Channel Host Bus Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ +#ifndef BFAD_BSG_H +#define BFAD_BSG_H + +#include "bfa_defs.h" +#include "bfa_defs_fcs.h" + +/* Definitions of vendor unique structures and command codes passed in + * using FC_BSG_HST_VENDOR message code. + */ +enum { +	IOCMD_IOC_ENABLE = 0x1, +	IOCMD_IOC_DISABLE, +	IOCMD_IOC_GET_ATTR, +	IOCMD_IOC_GET_INFO, +	IOCMD_IOC_GET_STATS, +	IOCMD_IOC_GET_FWSTATS, +	IOCMD_IOC_RESET_STATS, +	IOCMD_IOC_RESET_FWSTATS, +	IOCMD_IOC_SET_ADAPTER_NAME, +	IOCMD_IOC_SET_PORT_NAME, +	IOCMD_IOC_FW_SIG_INV, +	IOCMD_IOCFC_GET_ATTR, +	IOCMD_IOCFC_SET_INTR, +	IOCMD_PORT_ENABLE, +	IOCMD_PORT_DISABLE, +	IOCMD_PORT_GET_ATTR, +	IOCMD_PORT_GET_STATS, +	IOCMD_PORT_RESET_STATS, +	IOCMD_PORT_CFG_TOPO, +	IOCMD_PORT_CFG_SPEED, +	IOCMD_PORT_CFG_ALPA, +	IOCMD_PORT_CFG_MAXFRSZ, +	IOCMD_PORT_CLR_ALPA, +	IOCMD_PORT_BBCR_ENABLE, +	IOCMD_PORT_BBCR_DISABLE, +	IOCMD_PORT_BBCR_GET_ATTR, +	IOCMD_LPORT_GET_ATTR, +	IOCMD_LPORT_GET_RPORTS, +	IOCMD_LPORT_GET_STATS, +	IOCMD_LPORT_RESET_STATS, +	IOCMD_LPORT_GET_IOSTATS, +	IOCMD_RPORT_GET_ATTR, +	IOCMD_RPORT_GET_ADDR, +	IOCMD_RPORT_GET_STATS, +	IOCMD_RPORT_RESET_STATS, +	IOCMD_RPORT_SET_SPEED, +	IOCMD_VPORT_GET_ATTR, +	IOCMD_VPORT_GET_STATS, +	IOCMD_VPORT_RESET_STATS, +	IOCMD_FABRIC_GET_LPORTS, +	IOCMD_RATELIM_ENABLE, +	IOCMD_RATELIM_DISABLE, +	IOCMD_RATELIM_DEF_SPEED, +	IOCMD_FCPIM_FAILOVER, +	IOCMD_FCPIM_MODSTATS, +	IOCMD_FCPIM_MODSTATSCLR, +	IOCMD_FCPIM_DEL_ITN_STATS, +	IOCMD_ITNIM_GET_ATTR, +	IOCMD_ITNIM_GET_IOSTATS, +	IOCMD_ITNIM_RESET_STATS, +	IOCMD_ITNIM_GET_ITNSTATS, +	IOCMD_IOC_PCIFN_CFG, +	IOCMD_FCPORT_ENABLE, +	IOCMD_FCPORT_DISABLE, +	IOCMD_PCIFN_CREATE, +	IOCMD_PCIFN_DELETE, +	IOCMD_PCIFN_BW, +	IOCMD_ADAPTER_CFG_MODE, +	IOCMD_PORT_CFG_MODE, +	IOCMD_FLASH_ENABLE_OPTROM, +	IOCMD_FLASH_DISABLE_OPTROM, +	IOCMD_FAA_QUERY, +	IOCMD_CEE_GET_ATTR, +	IOCMD_CEE_GET_STATS, +	IOCMD_CEE_RESET_STATS, +	IOCMD_SFP_MEDIA, +	IOCMD_SFP_SPEED, +	IOCMD_FLASH_GET_ATTR, +	IOCMD_FLASH_ERASE_PART, +	IOCMD_FLASH_UPDATE_PART, +	IOCMD_FLASH_READ_PART, +	IOCMD_DIAG_TEMP, +	IOCMD_DIAG_MEMTEST, +	IOCMD_DIAG_LOOPBACK, +	IOCMD_DIAG_FWPING, +	IOCMD_DIAG_QUEUETEST, +	IOCMD_DIAG_SFP, +	IOCMD_DIAG_LED, +	IOCMD_DIAG_BEACON_LPORT, +	IOCMD_DIAG_LB_STAT, +	IOCMD_PHY_GET_ATTR, +	IOCMD_PHY_GET_STATS, +	IOCMD_PHY_UPDATE_FW, +	IOCMD_PHY_READ_FW, +	IOCMD_VHBA_QUERY, +	IOCMD_DEBUG_PORTLOG, +	IOCMD_DEBUG_FW_CORE, +	IOCMD_DEBUG_FW_STATE_CLR, +	IOCMD_DEBUG_PORTLOG_CLR, +	IOCMD_DEBUG_START_DTRC, +	IOCMD_DEBUG_STOP_DTRC, +	IOCMD_DEBUG_PORTLOG_CTL, +	IOCMD_FCPIM_PROFILE_ON, +	IOCMD_FCPIM_PROFILE_OFF, +	IOCMD_ITNIM_GET_IOPROFILE, +	IOCMD_FCPORT_GET_STATS, +	IOCMD_FCPORT_RESET_STATS, +	IOCMD_BOOT_CFG, +	IOCMD_BOOT_QUERY, +	IOCMD_PREBOOT_QUERY, +	IOCMD_ETHBOOT_CFG, +	IOCMD_ETHBOOT_QUERY, +	IOCMD_TRUNK_ENABLE, +	IOCMD_TRUNK_DISABLE, +	IOCMD_TRUNK_GET_ATTR, +	IOCMD_QOS_ENABLE, +	IOCMD_QOS_DISABLE, +	IOCMD_QOS_GET_ATTR, +	IOCMD_QOS_GET_VC_ATTR, +	IOCMD_QOS_GET_STATS, +	IOCMD_QOS_RESET_STATS, +	IOCMD_VF_GET_STATS, +	IOCMD_VF_RESET_STATS, +	IOCMD_FCPIM_LUNMASK_ENABLE, +	IOCMD_FCPIM_LUNMASK_DISABLE, +	IOCMD_FCPIM_LUNMASK_CLEAR, +	IOCMD_FCPIM_LUNMASK_QUERY, +	IOCMD_FCPIM_LUNMASK_ADD, +	IOCMD_FCPIM_LUNMASK_DELETE, +	IOCMD_DIAG_DPORT_ENABLE, +	IOCMD_DIAG_DPORT_DISABLE, +	IOCMD_QOS_SET_BW, +	IOCMD_FCPIM_THROTTLE_QUERY, +	IOCMD_FCPIM_THROTTLE_SET, +	IOCMD_TFRU_READ, +	IOCMD_TFRU_WRITE, +	IOCMD_FRUVPD_READ, +	IOCMD_FRUVPD_UPDATE, +	IOCMD_FRUVPD_GET_MAX_SIZE, +	IOCMD_DIAG_DPORT_SHOW, +	IOCMD_DIAG_DPORT_START, +}; + +struct bfa_bsg_gen_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +}; + +struct bfa_bsg_portlogctl_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	bfa_boolean_t	ctl; +	int		inst_no; +}; + +struct bfa_bsg_fcpim_profile_s { +	bfa_status_t    status; +	u16		bfad_num; +	u16		rsvd; +}; + +struct bfa_bsg_itnim_ioprofile_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		lpwwn; +	wwn_t		rpwwn; +	struct bfa_itnim_ioprofile_s ioprofile; +}; + +struct bfa_bsg_fcport_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	union bfa_fcport_stats_u stats; +}; + +struct bfa_bsg_ioc_name_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	char		name[BFA_ADAPTER_SYM_NAME_LEN]; +}; + +struct bfa_bsg_ioc_info_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	char		serialnum[64]; +	char		hwpath[BFA_STRING_32]; +	char		adapter_hwpath[BFA_STRING_32]; +	char		guid[BFA_ADAPTER_SYM_NAME_LEN*2]; +	char		name[BFA_ADAPTER_SYM_NAME_LEN]; +	char		port_name[BFA_ADAPTER_SYM_NAME_LEN]; +	char		eth_name[BFA_ADAPTER_SYM_NAME_LEN]; +	wwn_t		pwwn; +	wwn_t		nwwn; +	wwn_t		factorypwwn; +	wwn_t		factorynwwn; +	mac_t		mac; +	mac_t		factory_mac; /* Factory mac address */ +	mac_t		current_mac; /* Currently assigned mac address */ +	enum bfa_ioc_type_e	ioc_type; +	u16		pvid; /* Port vlan id */ +	u16		rsvd1; +	u32		host; +	u32		bandwidth; /* For PF support */ +	u32		rsvd2; +}; + +struct bfa_bsg_ioc_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_ioc_attr_s  ioc_attr; +}; + +struct bfa_bsg_ioc_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_ioc_stats_s ioc_stats; +}; + +struct bfa_bsg_ioc_fwstats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		buf_size; +	u32		rsvd1; +	u64		buf_ptr; +}; + +struct bfa_bsg_iocfc_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_iocfc_attr_s	iocfc_attr; +}; + +struct bfa_bsg_iocfc_intr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_iocfc_intr_attr_s attr; +}; + +struct bfa_bsg_port_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_port_attr_s	attr; +}; + +struct bfa_bsg_port_cfg_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		param; +	u32		rsvd1; +}; + +struct bfa_bsg_port_cfg_maxfrsize_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		maxfrsize; +}; + +struct bfa_bsg_port_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		buf_size; +	u32		rsvd1; +	u64		buf_ptr; +}; + +struct bfa_bsg_lport_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	struct bfa_lport_attr_s port_attr; +}; + +struct bfa_bsg_lport_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	struct bfa_lport_stats_s port_stats; +}; + +struct bfa_bsg_lport_iostats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	struct bfa_itnim_iostats_s iostats; +}; + +struct bfa_bsg_lport_get_rports_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	u64		rbuf_ptr; +	u32		nrports; +	u32		rsvd; +}; + +struct bfa_bsg_rport_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	wwn_t		rpwwn; +	u32		pid; +	u32		rsvd; +	struct bfa_rport_attr_s attr; +}; + +struct bfa_bsg_rport_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	wwn_t		rpwwn; +	struct bfa_rport_stats_s stats; +}; + +struct bfa_bsg_rport_scsi_addr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	wwn_t		rpwwn; +	u32		host; +	u32		bus; +	u32		target; +	u32		lun; +}; + +struct bfa_bsg_rport_reset_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	wwn_t		rpwwn; +}; + +struct bfa_bsg_rport_set_speed_s { +	bfa_status_t		status; +	u16			bfad_num; +	u16			vf_id; +	enum bfa_port_speed	speed; +	u32			rsvd; +	wwn_t			pwwn; +	wwn_t			rpwwn; +}; + +struct bfa_bsg_vport_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		vpwwn; +	struct bfa_vport_attr_s vport_attr; +}; + +struct bfa_bsg_vport_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		vpwwn; +	struct bfa_vport_stats_s vport_stats; +}; + +struct bfa_bsg_reset_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		vpwwn; +}; + +struct bfa_bsg_fabric_get_lports_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	u64		buf_ptr; +	u32		nports; +	u32		rsvd; +}; + +struct bfa_bsg_trl_speed_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	enum bfa_port_speed speed; +}; + +struct bfa_bsg_fcpim_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		param; +}; + +struct bfa_bsg_fcpim_modstats_s { +	bfa_status_t	status; +	u16		bfad_num; +	struct bfa_itnim_iostats_s modstats; +}; + +struct bfa_bsg_fcpim_del_itn_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	struct bfa_fcpim_del_itn_stats_s modstats; +}; + +struct bfa_bsg_fcpim_modstatsclr_s { +	bfa_status_t	status; +	u16		bfad_num; +}; + +struct bfa_bsg_itnim_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		lpwwn; +	wwn_t		rpwwn; +	struct bfa_itnim_attr_s	attr; +}; + +struct bfa_bsg_itnim_iostats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		lpwwn; +	wwn_t		rpwwn; +	struct bfa_itnim_iostats_s iostats; +}; + +struct bfa_bsg_itnim_itnstats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		lpwwn; +	wwn_t		rpwwn; +	struct bfa_itnim_stats_s itnstats; +}; + +struct bfa_bsg_pcifn_cfg_s { +	bfa_status_t		status; +	u16			bfad_num; +	u16			rsvd; +	struct bfa_ablk_cfg_s	pcifn_cfg; +}; + +struct bfa_bsg_pcifn_s { +	bfa_status_t		status; +	u16			bfad_num; +	u16			pcifn_id; +	u16			bw_min; +	u16			bw_max; +	u8			port; +	enum bfi_pcifn_class	pcifn_class; +	u8			rsvd[1]; +}; + +struct bfa_bsg_adapter_cfg_mode_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_adapter_cfg_mode_s	cfg; +}; + +struct bfa_bsg_port_cfg_mode_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		instance; +	struct bfa_port_cfg_mode_s cfg; +}; + +struct bfa_bsg_bbcr_enable_s { +	bfa_status_t    status; +	u16		bfad_num; +	u8		bb_scn; +	u8		rsvd; +}; + +struct bfa_bsg_bbcr_attr_s { +	bfa_status_t    status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_bbcr_attr_s attr; +}; + +struct bfa_bsg_faa_attr_s { +	bfa_status_t		status; +	u16			bfad_num; +	u16			rsvd; +	struct bfa_faa_attr_s	faa_attr; +}; + +struct bfa_bsg_cee_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		buf_size; +	u32		rsvd1; +	u64		buf_ptr; +}; + +struct bfa_bsg_cee_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		buf_size; +	u32		rsvd1; +	u64		buf_ptr; +}; + +struct bfa_bsg_sfp_media_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	enum bfa_defs_sfp_media_e media; +}; + +struct bfa_bsg_sfp_speed_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	enum bfa_port_speed speed; +}; + +struct bfa_bsg_flash_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_flash_attr_s attr; +}; + +struct bfa_bsg_flash_s { +	bfa_status_t	status; +	u16		bfad_num; +	u8		instance; +	u8		rsvd; +	enum  bfa_flash_part_type type; +	int		bufsz; +	u64		buf_ptr; +}; + +struct bfa_bsg_diag_get_temp_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_diag_results_tempsensor_s result; +}; + +struct bfa_bsg_diag_memtest_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd[3]; +	u32		pat; +	struct bfa_diag_memtest_result result; +	struct bfa_diag_memtest_s memtest; +}; + +struct bfa_bsg_diag_loopback_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	enum bfa_port_opmode opmode; +	enum bfa_port_speed speed; +	u32		lpcnt; +	u32		pat; +	struct bfa_diag_loopback_result_s result; +}; + +struct bfa_bsg_diag_dport_show_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_diag_dport_result_s result; +}; + +struct bfa_bsg_dport_enable_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u16		lpcnt; +	u16		pat; +}; + +struct bfa_bsg_diag_fwping_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		cnt; +	u32		pattern; +	struct bfa_diag_results_fwping result; +}; + +struct bfa_bsg_diag_qtest_s { +	bfa_status_t	status; +	u16	bfad_num; +	u16	rsvd; +	u32	force; +	u32	queue; +	struct bfa_diag_qtest_result_s result; +}; + +struct bfa_bsg_sfp_show_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct sfp_mem_s sfp; +}; + +struct bfa_bsg_diag_led_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_diag_ledtest_s ledtest; +}; + +struct bfa_bsg_diag_beacon_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	bfa_boolean_t   beacon; +	bfa_boolean_t   link_e2e_beacon; +	u32		second; +}; + +struct bfa_bsg_diag_lb_stat_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +}; + +struct bfa_bsg_phy_attr_s { +	bfa_status_t	status; +	u16	bfad_num; +	u16	instance; +	struct bfa_phy_attr_s	attr; +}; + +struct bfa_bsg_phy_s { +	bfa_status_t	status; +	u16	bfad_num; +	u16	instance; +	u64	bufsz; +	u64	buf_ptr; +}; + +struct bfa_bsg_debug_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		bufsz; +	int		inst_no; +	u64		buf_ptr; +	u64		offset; +}; + +struct bfa_bsg_phy_stats_s { +	bfa_status_t	status; +	u16	bfad_num; +	u16	instance; +	struct bfa_phy_stats_s	stats; +}; + +struct bfa_bsg_vhba_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		pcifn_id; +	struct bfa_vhba_attr_s	attr; +}; + +struct bfa_bsg_boot_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_boot_cfg_s	cfg; +}; + +struct bfa_bsg_preboot_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_boot_pbc_s	cfg; +}; + +struct bfa_bsg_ethboot_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct  bfa_ethboot_cfg_s  cfg; +}; + +struct bfa_bsg_trunk_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_trunk_attr_s attr; +}; + +struct bfa_bsg_qos_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_qos_attr_s	attr; +}; + +struct bfa_bsg_qos_vc_attr_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_qos_vc_attr_s attr; +}; + +struct bfa_bsg_qos_bw_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	struct bfa_qos_bw_s qos_bw; +}; + +struct bfa_bsg_vf_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	struct bfa_vf_stats_s	stats; +}; + +struct bfa_bsg_vf_reset_stats_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +}; + +struct bfa_bsg_fcpim_lunmask_query_s { +	bfa_status_t	status; +	u16		bfad_num; +	struct bfa_lunmask_cfg_s lun_mask; +}; + +struct bfa_bsg_fcpim_lunmask_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	wwn_t		pwwn; +	wwn_t		rpwwn; +	struct scsi_lun	lun; +}; + +struct bfa_bsg_fcpim_throttle_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		vf_id; +	struct bfa_defs_fcpim_throttle_s throttle; +}; + +#define BFA_TFRU_DATA_SIZE		64 +#define BFA_MAX_FRUVPD_TRANSFER_SIZE	0x1000 + +struct bfa_bsg_tfru_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		offset; +	u32		len; +	u8		data[BFA_TFRU_DATA_SIZE]; +}; + +struct bfa_bsg_fruvpd_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd1; +	u32		offset; +	u32		len; +	u8		data[BFA_MAX_FRUVPD_TRANSFER_SIZE]; +	u8		trfr_cmpl; +	u8		rsvd2[3]; +}; + +struct bfa_bsg_fruvpd_max_size_s { +	bfa_status_t	status; +	u16		bfad_num; +	u16		rsvd; +	u32		max_size; +}; + +struct bfa_bsg_fcpt_s { +	bfa_status_t    status; +	u16		vf_id; +	wwn_t		lpwwn; +	wwn_t		dpwwn; +	u32		tsecs; +	int		cts; +	enum fc_cos	cos; +	struct fchs_s	fchs; +}; +#define bfa_bsg_fcpt_t struct bfa_bsg_fcpt_s + +#pragma pack(1) +struct bfa_bsg_data { +	int payload_len; +	u64 payload; +}; +#pragma pack() + +#define bfad_chk_iocmd_sz(__payload_len, __hdrsz, __bufsz)	\ +	(((__payload_len) != ((__hdrsz) + (__bufsz))) ?		\ +	 BFA_STATUS_FAILED : BFA_STATUS_OK) + +#endif /* BFAD_BSG_H */ diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c index 1fedeeb4ac1..8e83d0474fe 100644 --- a/drivers/scsi/bfa/bfad_debugfs.c +++ b/drivers/scsi/bfa/bfad_debugfs.c @@ -16,6 +16,7 @@   */  #include <linux/debugfs.h> +#include <linux/export.h>  #include "bfad_drv.h"  #include "bfad_im.h" @@ -28,10 +29,10 @@   * mount -t debugfs none /sys/kernel/debug   *   * BFA Hierarchy: - *	- bfa/host# - * where the host number corresponds to the one under /sys/class/scsi_host/host# + *	- bfa/pci_dev:<pci_name> + * where the pci_name corresponds to the one under /sys/bus/pci/drivers/bfa   * - * Debugging service available per host: + * Debugging service available per pci_dev:   * fwtrc:  To collect current firmware trace.   * drvtrc: To collect current driver trace   * fwsave: To collect last saved fw trace as a result of firmware crash. @@ -90,7 +91,7 @@ bfad_debugfs_open_fwtrc(struct inode *inode, struct file *file)  	memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	rc = bfa_debug_fwtrc(&bfad->bfa, +	rc = bfa_ioc_debug_fwtrc(&bfad->bfa.ioc,  			fw_debug->debug_buffer,  			&fw_debug->buffer_len);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -134,7 +135,7 @@ bfad_debugfs_open_fwsave(struct inode *inode, struct file *file)  	memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);  	spin_lock_irqsave(&bfad->bfad_lock, flags); -	rc = bfa_debug_fwsave(&bfad->bfa, +	rc = bfa_ioc_debug_fwsave(&bfad->bfa.ioc,  			fw_debug->debug_buffer,  			&fw_debug->buffer_len);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -172,31 +173,9 @@ bfad_debugfs_open_reg(struct inode *inode, struct file *file)  static loff_t  bfad_debugfs_lseek(struct file *file, loff_t offset, int orig)  { -	struct bfad_debug_info *debug; -	loff_t pos = file->f_pos; - -	debug = file->private_data; - -	switch (orig) { -	case 0: -		file->f_pos = offset; -		break; -	case 1: -		file->f_pos += offset; -		break; -	case 2: -		file->f_pos = debug->buffer_len - offset; -		break; -	default: -		return -EINVAL; -	} - -	if (file->f_pos < 0 || file->f_pos > debug->buffer_len) { -		file->f_pos = pos; -		return -EINVAL; -	} - -	return file->f_pos; +	struct bfad_debug_info *debug = file->private_data; +	return fixed_size_llseek(file, offset, orig, +				debug->buffer_len);  }  static ssize_t @@ -208,16 +187,16 @@ bfad_debugfs_read(struct file *file, char __user *buf,  	if (!debug || !debug->debug_buffer)  		return 0; -	return memory_read_from_buffer(buf, nbytes, pos, +	return simple_read_from_buffer(buf, nbytes, pos,  				debug->debug_buffer, debug->buffer_len);  }  #define BFA_REG_CT_ADDRSZ	(0x40000)  #define BFA_REG_CB_ADDRSZ	(0x20000) -#define BFA_REG_ADDRSZ(__bfa)	\ -	((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ?	\ -		BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ) -#define BFA_REG_ADDRMSK(__bfa)  ((u32)(BFA_REG_ADDRSZ(__bfa) - 1)) +#define BFA_REG_ADDRSZ(__ioc)	\ +	((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ?	\ +	 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)) +#define BFA_REG_ADDRMSK(__ioc)	(BFA_REG_ADDRSZ(__ioc) - 1)  static bfa_status_t  bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len) @@ -236,7 +215,7 @@ bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)  			return BFA_STATUS_EINVAL;  	} else {  		/* CB register space 64KB */ -		if ((offset + (len<<2)) > BFA_REG_ADDRMSK(bfa)) +		if ((offset + (len<<2)) > BFA_REG_ADDRMSK(&bfa->ioc))  			return BFA_STATUS_EINVAL;  	}  	return BFA_STATUS_OK; @@ -254,7 +233,7 @@ bfad_debugfs_read_regrd(struct file *file, char __user *buf,  	if (!bfad->regdata)  		return 0; -	rc = memory_read_from_buffer(buf, nbytes, pos, +	rc = simple_read_from_buffer(buf, nbytes, pos,  			bfad->regdata, bfad->reglen);  	if ((*pos + nbytes) >= bfad->reglen) { @@ -279,15 +258,31 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,  	u32 *regbuf;  	void __iomem *rb, *reg_addr;  	unsigned long flags; +	void *kern_buf; + +	kern_buf = kzalloc(nbytes, GFP_KERNEL); + +	if (!kern_buf) { +		printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n", +				bfad->inst_no); +		return -ENOMEM; +	} -	rc = sscanf(buf, "%x:%x", &addr, &len); +	if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) { +		kfree(kern_buf); +		return -ENOMEM; +	} + +	rc = sscanf(kern_buf, "%x:%x", &addr, &len);  	if (rc < 2) {  		printk(KERN_INFO  			"bfad[%d]: %s failed to read user buf\n",  			bfad->inst_no, __func__); +		kfree(kern_buf);  		return -EINVAL;  	} +	kfree(kern_buf);  	kfree(bfad->regdata);  	bfad->regdata = NULL;  	bfad->reglen = 0; @@ -301,7 +296,7 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,  	bfad->reglen = len << 2;  	rb = bfa_ioc_bar0(ioc); -	addr &= BFA_REG_ADDRMSK(bfa); +	addr &= BFA_REG_ADDRMSK(ioc);  	/* offset and len sanity check */  	rc = bfad_reg_offset_check(bfa, addr, len); @@ -339,16 +334,32 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,  	int addr, val, rc;  	void __iomem *reg_addr;  	unsigned long flags; +	void *kern_buf; + +	kern_buf = kzalloc(nbytes, GFP_KERNEL); -	rc = sscanf(buf, "%x:%x", &addr, &val); +	if (!kern_buf) { +		printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n", +				bfad->inst_no); +		return -ENOMEM; +	} + +	if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) { +		kfree(kern_buf); +		return -ENOMEM; +	} + +	rc = sscanf(kern_buf, "%x:%x", &addr, &val);  	if (rc < 2) {  		printk(KERN_INFO  			"bfad[%d]: %s failed to read user buf\n",  			bfad->inst_no, __func__); +		kfree(kern_buf);  		return -EINVAL;  	} +	kfree(kern_buf); -	addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */ +	addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */  	/* offset and len sanity check */  	rc = bfad_reg_offset_check(bfa, addr, 1); @@ -359,7 +370,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,  		return -EINVAL;  	} -	reg_addr = (u32 *) ((u8 *) bfa_ioc_bar0(ioc) + addr); +	reg_addr = (bfa_ioc_bar0(ioc)) + addr;  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	writel(val, reg_addr);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -439,7 +450,7 @@ static const struct file_operations bfad_debugfs_op_regwr = {  struct bfad_debugfs_entry {  	const char *name; -	mode_t	mode; +	umode_t	mode;  	const struct file_operations *fops;  }; @@ -457,11 +468,9 @@ static atomic_t bfa_debugfs_port_count;  inline void  bfad_debugfs_init(struct bfad_port_s *port)  { -	struct bfad_im_port_s *im_port = port->im_port; -	struct bfad_s *bfad = im_port->bfad; -	struct Scsi_Host *shost = im_port->shost; +	struct bfad_s *bfad = port->bfad;  	const struct bfad_debugfs_entry *file; -	char name[16]; +	char name[64];  	int i;  	if (!bfa_debugfs_enable) @@ -478,17 +487,15 @@ bfad_debugfs_init(struct bfad_port_s *port)  		}  	} -	/* -	 * Setup the host# directory for the port, -	 * corresponds to the scsi_host num of this port. -	 */ -	snprintf(name, sizeof(name), "host%d", shost->host_no); +	/* Setup the pci_dev debugfs directory for the port */ +	snprintf(name, sizeof(name), "pci_dev:%s", bfad->pci_name);  	if (!port->port_debugfs_root) {  		port->port_debugfs_root =  			debugfs_create_dir(name, bfa_debugfs_root);  		if (!port->port_debugfs_root) {  			printk(KERN_WARNING -				"BFA host root dir creation failed\n"); +				"bfa %s: debugfs root creation failed\n", +				bfad->pci_name);  			goto err;  		} @@ -504,8 +511,8 @@ bfad_debugfs_init(struct bfad_port_s *port)  							file->fops);  			if (!bfad->bfad_dentry_files[i]) {  				printk(KERN_WARNING -					"BFA host%d: create %s entry failed\n", -					shost->host_no, file->name); +					"bfa %s: debugfs %s creation failed\n", +					bfad->pci_name, file->name);  				goto err;  			}  		} @@ -518,8 +525,7 @@ err:  inline void  bfad_debugfs_exit(struct bfad_port_s *port)  { -	struct bfad_im_port_s *im_port = port->im_port; -	struct bfad_s *bfad = im_port->bfad; +	struct bfad_s *bfad = port->bfad;  	int i;  	for (i = 0; i < ARRAY_SIZE(bfad_debugfs_files); i++) { @@ -529,10 +535,7 @@ bfad_debugfs_exit(struct bfad_port_s *port)  		}  	} -	/* -	 * Remove the host# directory for the port, -	 * corresponds to the scsi_host num of this port. -	*/ +	/* Remove the pci_dev debugfs directory for the port */  	if (port->port_debugfs_root) {  		debugfs_remove(port->port_debugfs_root);  		port->port_debugfs_root = NULL; diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 97f9b6c0937..8b97877d42c 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -26,7 +26,25 @@  #ifndef __BFAD_DRV_H__  #define __BFAD_DRV_H__ -#include "bfa_os_inc.h" +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/dma-mapping.h> +#include <linux/idr.h> +#include <linux/interrupt.h> +#include <linux/cdev.h> +#include <linux/fs.h> +#include <linux/delay.h> +#include <linux/vmalloc.h> +#include <linux/workqueue.h> +#include <linux/bitops.h> +#include <linux/aer.h> +#include <scsi/scsi.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_tcq.h> +#include <scsi/scsi_transport_fc.h> +#include <scsi/scsi_transport.h> +#include <scsi/scsi_bsg_fc.h> +#include <scsi/scsi_devinfo.h>  #include "bfa_modules.h"  #include "bfa_fcs.h" @@ -39,7 +57,7 @@  #ifdef BFA_DRIVER_VERSION  #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION  #else -#define BFAD_DRIVER_VERSION    "2.3.2.0" +#define BFAD_DRIVER_VERSION    "3.2.23.0"  #endif  #define BFAD_PROTO_NAME FCPI_NAME @@ -63,7 +81,9 @@  #define BFAD_HAL_INIT_FAIL			0x00000100  #define BFAD_FC4_PROBE_DONE			0x00000200  #define BFAD_PORT_DELETE			0x00000001 - +#define BFAD_INTX_ON				0x00000400 +#define BFAD_EEH_BUSY				0x00000800 +#define BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE	0x00001000  /*   * BFAD related definition   */ @@ -76,6 +96,8 @@   */  #define BFAD_LUN_QUEUE_DEPTH	32  #define BFAD_IO_MAX_SGE		SG_ALL +#define BFAD_MIN_SECTORS	128 /* 64k   */ +#define BFAD_MAX_SECTORS	0xFFFF  /* 32 MB */  #define bfad_isr_t irq_handler_t @@ -94,6 +116,7 @@ struct bfad_msix_s {  enum {  	BFA_TRC_LDRV_BFAD		= 1,  	BFA_TRC_LDRV_IM			= 2, +	BFA_TRC_LDRV_BSG		= 3,  };  enum bfad_port_pvb_type { @@ -173,8 +196,10 @@ struct bfad_s {  	struct bfa_pcidev_s hal_pcidev;  	struct bfa_ioc_pci_attr_s pci_attr;  	void __iomem   *pci_bar0_kva; +	void __iomem   *pci_bar2_kva;  	struct completion comp;  	struct completion suspend; +	struct completion enable_comp;  	struct completion disable_comp;  	bfa_boolean_t   disable_active;  	struct bfad_port_s     pport;	/* physical port of the BFAD */ @@ -202,6 +227,11 @@ struct bfad_s {  	char *regdata;  	u32 reglen;  	struct dentry *bfad_dentry_files[5]; +	struct list_head	free_aen_q; +	struct list_head	active_aen_q; +	struct bfa_aen_entry_s	aen_list[BFA_AEN_MAX_ENTRY]; +	spinlock_t		bfad_aen_spinlock; +	struct list_head	vport_list;  };  /* BFAD state machine events */ @@ -210,8 +240,8 @@ enum bfad_sm_event {  	BFAD_E_KTHREAD_CREATE_FAILED	= 2,  	BFAD_E_INIT			= 3,  	BFAD_E_INIT_SUCCESS		= 4, -	BFAD_E_INIT_FAILED		= 5, -	BFAD_E_INTR_INIT_FAILED		= 6, +	BFAD_E_HAL_INIT_FAILED		= 5, +	BFAD_E_INIT_FAILED		= 6,  	BFAD_E_FCS_EXIT_COMP		= 7,  	BFAD_E_EXIT_COMP		= 8,  	BFAD_E_STOP			= 9 @@ -257,34 +287,12 @@ struct bfad_hal_comp {  	struct completion comp;  }; -/* - * Macro to obtain the immediate lower power - * of two for the integer. - */ -#define nextLowerInt(x)                         \ -do {                                            \ -	int i;                                  \ -	(*x)--;					\ -	for (i = 1; i < (sizeof(int)*8); i <<= 1) \ -		(*x) = (*x) | (*x) >> i;	\ -	(*x)++;					\ -	(*x) = (*x) >> 1;			\ +#define BFA_LOG(level, bfad, mask, fmt, arg...)				\ +do {									\ +	if (((mask) == 4) || (level[1] <= '4'))				\ +		dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg);	\  } while (0) - -#define list_remove_head(list, entry, type, member)		\ -do {								\ -	entry = NULL;                                           \ -	if (!list_empty(list)) {                                \ -		entry = list_entry((list)->next, type, member);	\ -		list_del_init(&entry->member);			\ -	}							\ -} while (0) - -#define list_get_first(list, type, member)				\ -((list_empty(list)) ? NULL :						\ -	list_entry((list)->next, type, member)) -  bfa_status_t	bfad_vport_create(struct bfad_s *bfad, u16 vf_id,  				  struct bfa_lport_cfg_s *port_cfg,  				  struct device *dev); @@ -316,8 +324,8 @@ void		bfad_debugfs_exit(struct bfad_port_s *port);  void bfad_pci_remove(struct pci_dev *pdev);  int bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid); -void bfad_os_rport_online_wait(struct bfad_s *bfad); -int bfad_os_get_linkup_delay(struct bfad_s *bfad); +void bfad_rport_online_wait(struct bfad_s *bfad); +int bfad_get_linkup_delay(struct bfad_s *bfad);  int bfad_install_msix_handler(struct bfad_s *bfad);  extern struct idr bfad_im_port_index; @@ -337,7 +345,7 @@ extern int	num_sgpgs;  extern int      rport_del_timeout;  extern int      bfa_lun_queue_depth;  extern int      bfa_io_max_sge; -extern int      log_level; +extern int      bfa_log_level;  extern int      ioc_auto_recover;  extern int      bfa_linkup_delay;  extern int      msix_disable_cb; @@ -345,6 +353,7 @@ extern int      msix_disable_ct;  extern int      fdmi_enable;  extern int      supported_fc4s;  extern int	pcie_max_read_reqsz; +extern int	max_xfer_size;  extern int bfa_debugfs_enable;  extern struct mutex bfad_mutex; diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 8daa716739d..f067332bf76 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -19,9 +19,10 @@   *  bfad_im.c Linux driver IM module.   */ +#include <linux/export.h> +  #include "bfad_drv.h"  #include "bfad_im.h" -#include "bfa_cb_ioim.h"  #include "bfa_fcs.h"  BFA_TRC_FILE(LDRV, IM); @@ -30,8 +31,7 @@ DEFINE_IDR(bfad_im_port_index);  struct scsi_transport_template *bfad_im_scsi_transport_template;  struct scsi_transport_template *bfad_im_scsi_vport_transport_template;  static void bfad_im_itnim_work_handler(struct work_struct *work); -static int bfad_im_queuecommand(struct scsi_cmnd *cmnd, -				void (*done)(struct scsi_cmnd *)); +static int bfad_im_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmnd);  static int bfad_im_slave_alloc(struct scsi_device *sdev);  static void bfad_im_fc_rport_add(struct bfad_im_port_s  *im_port,  				struct bfad_itnim_s *itnim); @@ -73,9 +73,14 @@ bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,  		break; -	case BFI_IOIM_STS_ABORTED:  	case BFI_IOIM_STS_TIMEDOUT: +		host_status = DID_TIME_OUT; +		cmnd->result = ScsiResult(host_status, 0); +		break;  	case BFI_IOIM_STS_PATHTOV: +		host_status = DID_TRANSPORT_DISRUPTED; +		cmnd->result = ScsiResult(host_status, 0); +		break;  	default:  		host_status = DID_ERROR;  		cmnd->result = ScsiResult(host_status, 0); @@ -94,10 +99,10 @@ bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,  		if (!cmnd->result && itnim &&  			 (bfa_lun_queue_depth > cmnd->device->queue_depth)) {  			/* Queue depth adjustment for good status completion */ -			bfad_os_ramp_up_qdepth(itnim, cmnd->device); +			bfad_ramp_up_qdepth(itnim, cmnd->device);  		} else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) {  			/* qfull handling */ -			bfad_os_handle_qfull(itnim, cmnd->device); +			bfad_handle_qfull(itnim, cmnd->device);  		}  	} @@ -125,7 +130,7 @@ bfa_cb_ioim_good_comp(void *drv, struct bfad_ioim_s *dio)  		if (itnim_data) {  			itnim = itnim_data->itnim;  			if (itnim) -				bfad_os_ramp_up_qdepth(itnim, cmnd->device); +				bfad_ramp_up_qdepth(itnim, cmnd->device);  		}  	} @@ -177,21 +182,11 @@ bfad_im_info(struct Scsi_Host *shost)  	struct bfad_im_port_s *im_port =  			(struct bfad_im_port_s *) shost->hostdata[0];  	struct bfad_s *bfad = im_port->bfad; -	struct bfa_s *bfa = &bfad->bfa; -	struct bfa_ioc_s *ioc = &bfa->ioc; -	char model[BFA_ADAPTER_MODEL_NAME_LEN]; - -	bfa_get_adapter_model(bfa, model);  	memset(bfa_buf, 0, sizeof(bfa_buf)); -	if (ioc->ctdev) -		snprintf(bfa_buf, sizeof(bfa_buf), -		"Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s", -		 model, bfad->pci_name, BFAD_DRIVER_VERSION); -	else -		snprintf(bfa_buf, sizeof(bfa_buf), -		"Brocade FC Adapter, " "model: %s hwpath: %s driver: %s", -		model, bfad->pci_name, BFAD_DRIVER_VERSION); +	snprintf(bfa_buf, sizeof(bfa_buf), +		"Brocade FC/FCOE Adapter, " "hwpath: %s driver: %s", +		bfad->pci_name, BFAD_DRIVER_VERSION);  	return bfa_buf;  } @@ -216,7 +211,7 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	hal_io = (struct bfa_ioim_s *) cmnd->host_scribble;  	if (!hal_io) { -		/* IO has been completed, retrun success */ +		/* IO has been completed, return success */  		rc = SUCCESS;  		goto out;  	} @@ -226,7 +221,8 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)  	}  	bfa_trc(bfad, hal_io->iotag); -	BFA_LOG(KERN_INFO, bfad, log_level, "scsi%d: abort cmnd %p iotag %x\n", +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, +		"scsi%d: abort cmnd %p iotag %x\n",  		im_port->shost->host_no, cmnd, hal_io->iotag);  	(void) bfa_ioim_abort(hal_io);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -242,7 +238,7 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)  	cmnd->scsi_done(cmnd);  	bfa_trc(bfad, hal_io->iotag); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"scsi%d: complete abort 0x%p iotag 0x%x\n",  		im_port->shost->host_no, cmnd, hal_io->iotag);  	return SUCCESS; @@ -258,10 +254,11 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,  	struct bfa_tskim_s *tskim;  	struct bfa_itnim_s *bfa_itnim;  	bfa_status_t    rc = BFA_STATUS_OK; +	struct scsi_lun scsilun;  	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);  	if (!tskim) { -		BFA_LOG(KERN_ERR, bfad, log_level, +		BFA_LOG(KERN_ERR, bfad, bfa_log_level,  			"target reset, fail to allocate tskim\n");  		rc = BFA_STATUS_FAILED;  		goto out; @@ -274,7 +271,8 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,  	cmnd->host_scribble = NULL;  	cmnd->SCp.Status = 0;  	bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); -	bfa_tskim_start(tskim, bfa_itnim, (lun_t)0, +	memset(&scsilun, 0, sizeof(scsilun)); +	bfa_tskim_start(tskim, bfa_itnim, scsilun,  			    FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO);  out:  	return rc; @@ -301,6 +299,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)  	int             rc = SUCCESS;  	unsigned long   flags;  	enum bfi_tskim_status task_status; +	struct scsi_lun scsilun;  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	itnim = itnim_data->itnim; @@ -312,7 +311,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)  	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);  	if (!tskim) { -		BFA_LOG(KERN_ERR, bfad, log_level, +		BFA_LOG(KERN_ERR, bfad, bfa_log_level,  				"LUN reset, fail to allocate tskim");  		spin_unlock_irqrestore(&bfad->bfad_lock, flags);  		rc = FAILED; @@ -327,8 +326,8 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)  	cmnd->SCp.ptr = (char *)&wq;  	cmnd->SCp.Status = 0;  	bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); -	bfa_tskim_start(tskim, bfa_itnim, -			    bfad_int_to_lun(cmnd->device->lun), +	int_to_scsilun(cmnd->device->lun, &scsilun); +	bfa_tskim_start(tskim, bfa_itnim, scsilun,  			    FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -337,7 +336,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)  	task_status = cmnd->SCp.Status >> 1;  	if (task_status != BFI_TSKIM_STS_OK) { -		BFA_LOG(KERN_ERR, bfad, log_level, +		BFA_LOG(KERN_ERR, bfad, bfa_log_level,  			"LUN reset failure, status: %d\n", task_status);  		rc = FAILED;  	} @@ -364,7 +363,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)  	spin_lock_irqsave(&bfad->bfad_lock, flags);  	for (i = 0; i < MAX_FCP_TARGET; i++) { -		itnim = bfad_os_get_itnim(im_port, i); +		itnim = bfad_get_itnim(im_port, i);  		if (itnim) {  			cmnd->SCp.ptr = (char *)&wq;  			rc = bfad_im_target_reset_send(bfad, cmnd, itnim); @@ -381,7 +380,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)  			task_status = cmnd->SCp.Status >> 1;  			if (task_status != BFI_TSKIM_STS_OK) { -				BFA_LOG(KERN_ERR, bfad, log_level, +				BFA_LOG(KERN_ERR, bfad, bfa_log_level,  					"target reset failure,"  					" status: %d\n", task_status);  				err_cnt++; @@ -447,7 +446,7 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)  	struct bfad_im_s	*im = itnim_drv->im;  	/* online to free state transtion should not happen */ -	bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE); +	WARN_ON(itnim_drv->state == ITNIM_STATE_ONLINE);  	itnim_drv->queue_work = 1;  	/* offline request is not yet done, use the same request to free */ @@ -461,7 +460,7 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)  	fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);  	wwn2str(wwpn_str, wwpn);  	fcid2str(fcid_str, fcid); -	BFA_LOG(KERN_INFO, bfad, log_level, +	BFA_LOG(KERN_INFO, bfad, bfa_log_level,  		"ITNIM FREE scsi%d: FCID: %s WWPN: %s\n",  		port->im_port->shost->host_no,  		fcid_str, wwpn_str); @@ -529,23 +528,16 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,  	int error = 1;  	mutex_lock(&bfad_mutex); -	if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) { +	error = idr_alloc(&bfad_im_port_index, im_port, 0, 0, GFP_KERNEL); +	if (error < 0) {  		mutex_unlock(&bfad_mutex); -		printk(KERN_WARNING "idr_pre_get failure\n"); +		printk(KERN_WARNING "idr_alloc failure\n");  		goto out;  	} - -	error = idr_get_new(&bfad_im_port_index, im_port, -					 &im_port->idr_id); -	if (error) { -		mutex_unlock(&bfad_mutex); -		printk(KERN_WARNING "idr_get_new failure\n"); -		goto out; -	} - +	im_port->idr_id = error;  	mutex_unlock(&bfad_mutex); -	im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad); +	im_port->shost = bfad_scsi_host_alloc(im_port, bfad);  	if (!im_port->shost) {  		error = 1;  		goto out_free_idr; @@ -570,9 +562,6 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,  		goto out_fc_rel;  	} -	/* setup host fixed attribute if the lk supports */ -	bfad_os_fc_host_init(im_port); -  	return 0;  out_fc_rel: @@ -590,7 +579,7 @@ void  bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)  {  	bfa_trc(bfad, bfad->inst_no); -	BFA_LOG(KERN_INFO, bfad, log_level, "Free scsi%d\n", +	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "Free scsi%d\n",  			im_port->shost->host_no);  	fc_remove_host(im_port->shost); @@ -662,47 +651,69 @@ bfad_im_port_clean(struct bfad_im_port_s *im_port)  	}  	/* the itnim_mapped_list must be empty at this time */ -	bfa_assert(list_empty(&im_port->itnim_mapped_list)); +	WARN_ON(!list_empty(&im_port->itnim_mapped_list));  	spin_unlock_irqrestore(&bfad->bfad_lock, flags);  } +static void bfad_aen_im_notify_handler(struct work_struct *work) +{ +	struct bfad_im_s *im = +		container_of(work, struct bfad_im_s, aen_im_notify_work); +	struct bfa_aen_entry_s *aen_entry; +	struct bfad_s *bfad = im->bfad; +	struct Scsi_Host *shost = bfad->pport.im_port->shost; +	void *event_data; +	unsigned long flags; + +	while (!list_empty(&bfad->active_aen_q)) { +		spin_lock_irqsave(&bfad->bfad_aen_spinlock, flags); +		bfa_q_deq(&bfad->active_aen_q, &aen_entry); +		spin_unlock_irqrestore(&bfad->bfad_aen_spinlock, flags); +		event_data = (char *)aen_entry + sizeof(struct list_head); +		fc_host_post_vendor_event(shost, fc_get_event_number(), +				sizeof(struct bfa_aen_entry_s) - +				sizeof(struct list_head), +				(char *)event_data, BFAD_NL_VENDOR_ID); +		spin_lock_irqsave(&bfad->bfad_aen_spinlock, flags); +		list_add_tail(&aen_entry->qe, &bfad->free_aen_q); +		spin_unlock_irqrestore(&bfad->bfad_aen_spinlock, flags); +	} +} +  bfa_status_t  bfad_im_probe(struct bfad_s *bfad)  {  	struct bfad_im_s      *im; -	bfa_status_t    rc = BFA_STATUS_OK;  	im = kzalloc(sizeof(struct bfad_im_s), GFP_KERNEL); -	if (im == NULL) { -		rc = BFA_STATUS_ENOMEM; -		goto ext; -	} +	if (im == NULL) +		return BFA_STATUS_ENOMEM;  	bfad->im = im;  	im->bfad = bfad; -	if (bfad_os_thread_workq(bfad) != BFA_STATUS_OK) { +	if (bfad_thread_workq(bfad) != BFA_STATUS_OK) {  		kfree(im); -		rc = BFA_STATUS_FAILED; +		return BFA_STATUS_FAILED;  	} -ext: -	return rc; +	INIT_WORK(&im->aen_im_notify_work, bfad_aen_im_notify_handler); +	return BFA_STATUS_OK;  }  void  bfad_im_probe_undo(struct bfad_s *bfad)  {  	if (bfad->im) { -		bfad_os_destroy_workq(bfad->im); +		bfad_destroy_workq(bfad->im);  		kfree(bfad->im);  		bfad->im = NULL;  	}  }  struct Scsi_Host * -bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad) +bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)  {  	struct scsi_host_template *sht; @@ -711,13 +722,16 @@ bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)  	else  		sht = &bfad_im_vport_template; +	if (max_xfer_size != BFAD_MAX_SECTORS >> 1) +		sht->max_sectors = max_xfer_size << 1; +  	sht->sg_tablesize = bfad->cfg_data.io_max_sge;  	return scsi_host_alloc(sht, sizeof(unsigned long));  }  void -bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) +bfad_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)  {  	if (!(im_port->flags & BFAD_PORT_DELETE))  		flush_workqueue(bfad->im->drv_workq); @@ -727,7 +741,7 @@ bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)  }  void -bfad_os_destroy_workq(struct bfad_im_s *im) +bfad_destroy_workq(struct bfad_im_s *im)  {  	if (im && im->drv_workq) {  		flush_workqueue(im->drv_workq); @@ -737,7 +751,7 @@ bfad_os_destroy_workq(struct bfad_im_s *im)  }  bfa_status_t -bfad_os_thread_workq(struct bfad_s *bfad) +bfad_thread_workq(struct bfad_s *bfad)  {  	struct bfad_im_s      *im = bfad->im; @@ -788,7 +802,8 @@ struct scsi_host_template bfad_im_scsi_host_template = {  	.cmd_per_lun = 3,  	.use_clustering = ENABLE_CLUSTERING,  	.shost_attrs = bfad_im_host_attrs, -	.max_sectors = 0xFFFF, +	.max_sectors = BFAD_MAX_SECTORS, +	.vendor_id = BFA_PCI_VENDOR_ID_BROCADE,  };  struct scsi_host_template bfad_im_vport_template = { @@ -809,7 +824,7 @@ struct scsi_host_template bfad_im_vport_template = {  	.cmd_per_lun = 3,  	.use_clustering = ENABLE_CLUSTERING,  	.shost_attrs = bfad_im_vport_attrs, -	.max_sectors = 0xFFFF, +	.max_sectors = BFAD_MAX_SECTORS,  };  bfa_status_t @@ -841,7 +856,7 @@ bfad_im_module_exit(void)  }  void -bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev) +bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)  {  	struct scsi_device *tmp_sdev; @@ -869,7 +884,7 @@ bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)  }  void -bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev) +bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)  {  	struct scsi_device *tmp_sdev; @@ -883,7 +898,7 @@ bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)  }  struct bfad_itnim_s * -bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id) +bfad_get_itnim(struct bfad_im_port_s *im_port, int id)  {  	struct bfad_itnim_s   *itnim = NULL; @@ -897,22 +912,78 @@ bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id)  }  /* + * Function is invoked from the SCSI Host Template slave_alloc() entry point. + * Has the logic to query the LUN Mask database to check if this LUN needs to + * be made visible to the SCSI mid-layer or not. + * + * Returns BFA_STATUS_OK if this LUN needs to be added to the OS stack. + * Returns -ENXIO to notify SCSI mid-layer to not add this LUN to the OS stack. + */ +static int +bfad_im_check_if_make_lun_visible(struct scsi_device *sdev, +				  struct fc_rport *rport) +{ +	struct bfad_itnim_data_s *itnim_data = +				(struct bfad_itnim_data_s *) rport->dd_data; +	struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa; +	struct bfa_rport_s *bfa_rport = itnim_data->itnim->bfa_itnim->rport; +	struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(bfa); +	int i = 0, ret = -ENXIO; + +	for (i = 0; i < MAX_LUN_MASK_CFG; i++) { +		if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE && +		    scsilun_to_int(&lun_list[i].lun) == sdev->lun && +		    lun_list[i].rp_tag == bfa_rport->rport_tag && +		    lun_list[i].lp_tag == (u8)bfa_rport->rport_info.lp_tag) { +			ret = BFA_STATUS_OK; +			break; +		} +	} +	return ret; +} + +/*   * Scsi_Host template entry slave_alloc   */  static int  bfad_im_slave_alloc(struct scsi_device *sdev)  {  	struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); +	struct bfad_itnim_data_s *itnim_data; +	struct bfa_s *bfa;  	if (!rport || fc_remote_port_chkready(rport))  		return -ENXIO; +	itnim_data = (struct bfad_itnim_data_s *) rport->dd_data; +	bfa = itnim_data->itnim->bfa_itnim->bfa; + +	if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) { +		/* +		 * We should not mask LUN 0 - since this will translate +		 * to no LUN / TARGET for SCSI ml resulting no scan. +		 */ +		if (sdev->lun == 0) { +			sdev->sdev_bflags |= BLIST_NOREPORTLUN | +					     BLIST_SPARSELUN; +			goto done; +		} + +		/* +		 * Query LUN Mask configuration - to expose this LUN +		 * to the SCSI mid-layer or to mask it. +		 */ +		if (bfad_im_check_if_make_lun_visible(sdev, rport) != +							BFA_STATUS_OK) +			return -ENXIO; +	} +done:  	sdev->hostdata = rport->dd_data;  	return 0;  } -static u32 +u32  bfad_im_supported_speeds(struct bfa_s *bfa)  {  	struct bfa_ioc_attr_s *ioc_attr; @@ -922,8 +993,11 @@ bfad_im_supported_speeds(struct bfa_s *bfa)  	if (!ioc_attr)  		return 0; -	bfa_get_attr(bfa, ioc_attr); -	if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) { +	bfa_ioc_get_attr(&bfa->ioc, ioc_attr); +	if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_16GBPS) +		supported_speed |=  FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT | +				FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT; +	else if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {  		if (ioc_attr->adapter_attr.is_mezz) {  			supported_speed |= FC_PORTSPEED_8GBIT |  				FC_PORTSPEED_4GBIT | @@ -944,7 +1018,7 @@ bfad_im_supported_speeds(struct bfa_s *bfa)  }  void -bfad_os_fc_host_init(struct bfad_im_port_s *im_port) +bfad_fc_host_init(struct bfad_im_port_s *im_port)  {  	struct Scsi_Host *host = im_port->shost;  	struct bfad_s         *bfad = im_port->bfad; @@ -968,7 +1042,7 @@ bfad_os_fc_host_init(struct bfad_im_port_s *im_port)  	/* For fibre channel services type 0x20 */  	fc_host_supported_fc4s(host)[7] = 1; -	strncpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname, +	strlcpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,  		BFA_SYMNAME_MAXLEN);  	sprintf(fc_host_symbolic_name(host), "%s", symname); @@ -988,7 +1062,7 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)  	rport_ids.port_name =  		cpu_to_be64(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));  	rport_ids.port_id = -		bfa_os_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim)); +		bfa_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim));  	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;  	itnim->fc_rport = fc_rport = @@ -1013,6 +1087,8 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)  	    && (fc_rport->scsi_target_id < MAX_FCP_TARGET))  		itnim->scsi_tgt_id = fc_rport->scsi_target_id; +	itnim->channel = fc_rport->channel; +  	return;  } @@ -1049,7 +1125,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)  			fcid2str(fcid_str, fcid);  			list_add_tail(&itnim->list_entry,  				&im_port->itnim_mapped_list); -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"ITNIM ONLINE Target: %d:0:%d "  				"FCID: %s WWPN: %s\n",  				im_port->shost->host_no, @@ -1082,7 +1158,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)  			wwn2str(wwpn_str, wwpn);  			fcid2str(fcid_str, fcid);  			list_del(&itnim->list_entry); -			BFA_LOG(KERN_INFO, bfad, log_level, +			BFA_LOG(KERN_INFO, bfad, bfa_log_level,  				"ITNIM OFFLINE Target: %d:0:%d "  				"FCID: %s WWPN: %s\n",  				im_port->shost->host_no, @@ -1109,7 +1185,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)  		kfree(itnim);  		break;  	default: -		bfa_assert(0); +		WARN_ON(1);  		break;  	} @@ -1120,7 +1196,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)   * Scsi_Host template entry, queue a SCSI command to the BFAD.   */  static int -bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) +bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))  {  	struct bfad_im_port_s *im_port =  		(struct bfad_im_port_s *) cmnd->device->host->hostdata[0]; @@ -1140,6 +1216,15 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))  		return 0;  	} +	if (bfad->bfad_flags & BFAD_EEH_BUSY) { +		if (bfad->bfad_flags & BFAD_EEH_PCI_CHANNEL_IO_PERM_FAILURE) +			cmnd->result = DID_NO_CONNECT << 16; +		else +			cmnd->result = DID_REQUEUE << 16; +		done(cmnd); +		return 0; +	} +  	sg_cnt = scsi_dma_map(cmnd);  	if (sg_cnt < 0)  		return SCSI_MLQUEUE_HOST_BUSY; @@ -1172,7 +1257,6 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))  	}  	cmnd->host_scribble = (char *)hal_io; -	bfa_trc_fp(bfad, hal_io->iotag);  	bfa_ioim_start(hal_io);  	spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -1187,8 +1271,10 @@ out_fail_cmd:  	return 0;  } +static DEF_SCSI_QCMD(bfad_im_queuecommand) +  void -bfad_os_rport_online_wait(struct bfad_s *bfad) +bfad_rport_online_wait(struct bfad_s *bfad)  {  	int i;  	int rport_delay = 10; @@ -1216,7 +1302,7 @@ bfad_os_rport_online_wait(struct bfad_s *bfad)  }  int -bfad_os_get_linkup_delay(struct bfad_s *bfad) +bfad_get_linkup_delay(struct bfad_s *bfad)  {  	u8		nwwns = 0;  	wwn_t		wwns[BFA_PREBOOT_BOOTLUN_MAX]; diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h index b038c0e0892..f6c1023e502 100644 --- a/drivers/scsi/bfa/bfad_im.h +++ b/drivers/scsi/bfa/bfad_im.h @@ -37,6 +37,7 @@ int  bfad_im_scsi_host_alloc(struct bfad_s *bfad,  		struct bfad_im_port_s *im_port, struct device *dev);  void bfad_im_scsi_host_free(struct bfad_s *bfad,  				struct bfad_im_port_s *im_port); +u32 bfad_im_supported_speeds(struct bfa_s *bfa);  #define MAX_FCP_TARGET 1024  #define MAX_FCP_LUN 16384 @@ -91,6 +92,7 @@ struct bfad_itnim_s {  	struct fc_rport *fc_rport;  	struct bfa_itnim_s *bfa_itnim;  	u16        scsi_tgt_id; +	u16	   channel;  	u16        queue_work;  	unsigned long	last_ramp_up_time;  	unsigned long	last_queue_full_time; @@ -115,19 +117,41 @@ struct bfad_im_s {  	struct bfad_s         *bfad;  	struct workqueue_struct *drv_workq;  	char            drv_workq_name[KOBJ_NAME_LEN]; +	struct work_struct	aen_im_notify_work;  }; -struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, +#define bfad_get_aen_entry(_drv, _entry) do {				\ +	unsigned long	_flags;						\ +	spin_lock_irqsave(&(_drv)->bfad_aen_spinlock, _flags);		\ +	bfa_q_deq(&(_drv)->free_aen_q, &(_entry));			\ +	if (_entry)							\ +		list_add_tail(&(_entry)->qe, &(_drv)->active_aen_q);	\ +	spin_unlock_irqrestore(&(_drv)->bfad_aen_spinlock, _flags);	\ +} while (0) + +/* post fc_host vendor event */ +#define bfad_im_post_vendor_event(_entry, _drv, _cnt, _cat, _evt) do {	      \ +	do_gettimeofday(&(_entry)->aen_tv);				      \ +	(_entry)->bfad_num = (_drv)->inst_no;				      \ +	(_entry)->seq_num = (_cnt);					      \ +	(_entry)->aen_category = (_cat);				      \ +	(_entry)->aen_type = (_evt);					      \ +	if ((_drv)->bfad_flags & BFAD_FC4_PROBE_DONE)			      \ +		queue_work((_drv)->im->drv_workq,			      \ +			   &(_drv)->im->aen_im_notify_work);		      \ +} while (0) + +struct Scsi_Host *bfad_scsi_host_alloc(struct bfad_im_port_s *im_port,  				struct bfad_s *); -bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad); -void bfad_os_destroy_workq(struct bfad_im_s *im); -void bfad_os_fc_host_init(struct bfad_im_port_s *im_port); -void bfad_os_scsi_host_free(struct bfad_s *bfad, +bfa_status_t bfad_thread_workq(struct bfad_s *bfad); +void bfad_destroy_workq(struct bfad_im_s *im); +void bfad_fc_host_init(struct bfad_im_port_s *im_port); +void bfad_scsi_host_free(struct bfad_s *bfad,  				 struct bfad_im_port_s *im_port); -void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, +void bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim,  				 struct scsi_device *sdev); -void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev); -struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id); +void bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev); +struct bfad_itnim_s *bfad_get_itnim(struct bfad_im_port_s *im_port, int id);  extern struct scsi_host_template bfad_im_scsi_host_template;  extern struct scsi_host_template bfad_im_vport_template; @@ -141,29 +165,33 @@ extern struct device_attribute *bfad_im_vport_attrs[];  irqreturn_t bfad_intx(int irq, void *dev_id); -/* Firmware releated */ -#define BFAD_FW_FILE_CT_FC      "ctfw_fc.bin" -#define BFAD_FW_FILE_CT_CNA     "ctfw_cna.bin" -#define BFAD_FW_FILE_CB_FC      "cbfw_fc.bin" - -u32 *bfad_get_firmware_buf(struct pci_dev *pdev); -u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image, -		u32 *bfi_image_size, char *fw_name); - -static inline u32 * -bfad_load_fwimg(struct pci_dev *pdev) -{ -	return bfad_get_firmware_buf(pdev); -} - -static inline void -bfad_free_fwimg(void) -{ -	if (bfi_image_ct_fc_size && bfi_image_ct_fc) -		vfree(bfi_image_ct_fc); -	if (bfi_image_ct_cna_size && bfi_image_ct_cna) -		vfree(bfi_image_ct_cna); -	if (bfi_image_cb_fc_size && bfi_image_cb_fc) -		vfree(bfi_image_cb_fc); -} +int bfad_im_bsg_request(struct fc_bsg_job *job); +int bfad_im_bsg_timeout(struct fc_bsg_job *job); + +/* + * Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the + * SCSI mid-layer to choose LUN Scanning mode REPORT_LUNS vs. Sequential Scan + * + * Internally iterate's over all the ITNIM's part of the im_port & set's the + * sdev_bflags for the scsi_device associated with LUN #0. + */ +#define bfad_reset_sdev_bflags(__im_port, __lunmask_cfg) do {		\ +	struct scsi_device *__sdev = NULL;				\ +	struct bfad_itnim_s *__itnim = NULL;				\ +	u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN;		\ +	list_for_each_entry(__itnim, &((__im_port)->itnim_mapped_list),	\ +			    list_entry) {				\ +		__sdev = scsi_device_lookup((__im_port)->shost,		\ +					    __itnim->channel,		\ +					    __itnim->scsi_tgt_id, 0);	\ +		if (__sdev) {						\ +			if ((__lunmask_cfg) == BFA_TRUE)		\ +				__sdev->sdev_bflags |= scan_flags;	\ +			else						\ +				__sdev->sdev_bflags &= ~scan_flags;	\ +			scsi_device_put(__sdev);			\ +		}							\ +	}								\ +} while (0) +  #endif diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index 58796d1284b..9ef91f907de 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -23,17 +23,30 @@  #pragma pack(1) +/* Per dma segment max size */ +#define BFI_MEM_DMA_SEG_SZ	(131072) + +/* Get number of dma segments required */ +#define BFI_MEM_DMA_NSEGS(_num_reqs, _req_sz)				\ +	((u16)(((((_num_reqs) * (_req_sz)) + BFI_MEM_DMA_SEG_SZ - 1) &	\ +	 ~(BFI_MEM_DMA_SEG_SZ - 1)) / BFI_MEM_DMA_SEG_SZ)) + +/* Get num dma reqs - that fit in a segment */ +#define BFI_MEM_NREQS_SEG(_rqsz) (BFI_MEM_DMA_SEG_SZ / (_rqsz)) + +/* Get segment num from tag */ +#define BFI_MEM_SEG_FROM_TAG(_tag, _rqsz) ((_tag) / BFI_MEM_NREQS_SEG(_rqsz)) + +/* Get dma req offset in a segment */ +#define BFI_MEM_SEG_REQ_OFFSET(_tag, _sz)	\ +	((_tag) - (BFI_MEM_SEG_FROM_TAG(_tag, _sz) * BFI_MEM_NREQS_SEG(_sz))) +  /*   * BFI FW image type   */  #define	BFI_FLASH_CHUNK_SZ			256	/*  Flash chunk size */  #define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32)) -enum { -	BFI_IMAGE_CB_FC, -	BFI_IMAGE_CT_FC, -	BFI_IMAGE_CT_CNA, -	BFI_IMAGE_MAX, -}; +#define BFI_FLASH_IMAGE_SZ		0x100000  /*   * Msg header common to all msgs @@ -43,17 +56,20 @@ struct bfi_mhdr_s {  	u8		msg_id;		/*  msg opcode with in the class   */  	union {  		struct { -			u8	rsvd; -			u8	lpu_id;	/*  msg destination		    */ +			u8	qid; +			u8	fn_lpu;	/*  msg destination		    */  		} h2i;  		u16	i2htok;	/*  token in msgs to host	    */  	} mtag;  }; -#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\ +#define bfi_fn_lpu(__fn, __lpu)	((__fn) << 1 | (__lpu)) +#define bfi_mhdr_2_fn(_mh)	((_mh)->mtag.h2i.fn_lpu >> 1) + +#define bfi_h2i_set(_mh, _mc, _op, _fn_lpu) do {		\  	(_mh).msg_class		= (_mc);      \  	(_mh).msg_id		= (_op);      \ -	(_mh).mtag.h2i.lpu_id	= (_lpuid);      \ +	(_mh).mtag.h2i.fn_lpu	= (_fn_lpu);      \  } while (0)  #define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\ @@ -95,16 +111,16 @@ enum {   */  union bfi_addr_u {  	struct { -		u32	addr_lo; -		u32	addr_hi; +		__be32	addr_lo; +		__be32	addr_hi;  	} a32;  };  /* - * Scatter Gather Element + * Scatter Gather Element used for fast-path IO requests   */  struct bfi_sge_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN  	u32	flags:2,  			rsvd:2,  			sg_len:28; @@ -116,6 +132,14 @@ struct bfi_sge_s {  	union bfi_addr_u sga;  }; +/** + * Generic DMA addr-len pair. + */ +struct bfi_alen_s { +	union bfi_addr_u	al_addr;	/* DMA addr of buffer	*/ +	u32			al_len;		/* length of buffer	*/ +}; +  /*   * Scatter Gather Page   */ @@ -127,6 +151,12 @@ struct bfi_sgpg_s {  	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];  }; +/* FCP module definitions */ +#define BFI_IO_MAX	(2000) +#define BFI_IOIM_SNSLEN	(256) +#define BFI_IOIM_SNSBUF_SEGS	\ +	BFI_MEM_DMA_NSEGS(BFI_IO_MAX, BFI_IOIM_SNSLEN) +  /*   * Large Message structure - 128 Bytes size Msgs   */ @@ -149,18 +179,29 @@ struct bfi_mbmsg_s {  };  /* + * Supported PCI function class codes (personality) + */ +enum bfi_pcifn_class { +	BFI_PCIFN_CLASS_FC  = 0x0c04, +	BFI_PCIFN_CLASS_ETH = 0x0200, +}; + +/*   * Message Classes   */  enum bfi_mclass {  	BFI_MC_IOC		= 1,	/*  IO Controller (IOC)	    */ +	BFI_MC_DIAG		= 2,    /*  Diagnostic Msgs            */ +	BFI_MC_FLASH		= 3,	/*  Flash message class	*/ +	BFI_MC_CEE		= 4,	/*  CEE	*/  	BFI_MC_FCPORT		= 5,	/*  FC port			    */  	BFI_MC_IOCFC		= 6,	/*  FC - IO Controller (IOC)	    */ -	BFI_MC_LL               = 7,    /*  Link Layer                      */ +	BFI_MC_ABLK		= 7,	/*  ASIC block configuration	    */  	BFI_MC_UF		= 8,	/*  Unsolicited frame receive	    */  	BFI_MC_FCXP		= 9,	/*  FC Transport		    */  	BFI_MC_LPS		= 10,	/*  lport fc login services	    */  	BFI_MC_RPORT		= 11,	/*  Remote port		    */ -	BFI_MC_ITNIM		= 12,	/*  I-T nexus (Initiator mode)	    */ +	BFI_MC_ITN		= 12,	/*  I-T nexus (Initiator mode)	    */  	BFI_MC_IOIM_READ	= 13,	/*  read IO (Initiator mode)	    */  	BFI_MC_IOIM_WRITE	= 14,	/*  write IO (Initiator mode)	    */  	BFI_MC_IOIM_IO		= 15,	/*  IO (Initiator mode)	    */ @@ -168,30 +209,38 @@ enum bfi_mclass {  	BFI_MC_IOIM_IOCOM	= 17,	/*  good IO completion		    */  	BFI_MC_TSKIM		= 18,	/*  Initiator Task management	    */  	BFI_MC_PORT		= 21,	/*  Physical port		    */ -	BFI_MC_MAX		= 32 +	BFI_MC_SFP		= 22,	/*  SFP module	*/ +	BFI_MC_PHY		= 25,   /*  External PHY message class	*/ +	BFI_MC_FRU		= 34, +	BFI_MC_MAX		= 35  };  #define BFI_IOC_MAX_CQS		4  #define BFI_IOC_MAX_CQS_ASIC	8  #define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */ -#define BFI_BOOT_TYPE_OFF		8 -#define BFI_BOOT_LOADER_OFF		12 - -#define BFI_BOOT_TYPE_NORMAL		0 -#define	BFI_BOOT_TYPE_FLASH		1 -#define	BFI_BOOT_TYPE_MEMTEST		2 - -#define BFI_BOOT_LOADER_OS		0 -#define BFI_BOOT_LOADER_BIOS		1 -#define BFI_BOOT_LOADER_UEFI		2 -  /*   *----------------------------------------------------------------------   *				IOC   *----------------------------------------------------------------------   */ +/* + * Different asic generations + */ +enum bfi_asic_gen { +	BFI_ASIC_GEN_CB		= 1,	/* crossbow 8G FC		*/ +	BFI_ASIC_GEN_CT		= 2,	/* catapult 8G FC or 10G CNA	*/ +	BFI_ASIC_GEN_CT2	= 3,	/* catapult-2 16G FC or 10G CNA	*/ +}; + +enum bfi_asic_mode { +	BFI_ASIC_MODE_FC	= 1,	/* FC upto 8G speed		*/ +	BFI_ASIC_MODE_FC16	= 2,	/* FC upto 16G speed		*/ +	BFI_ASIC_MODE_ETH	= 3,	/* Ethernet ports		*/ +	BFI_ASIC_MODE_COMBO	= 4,	/* FC 16G and Ethernet 10G port	*/ +}; +  enum bfi_ioc_h2i_msgs {  	BFI_IOC_H2I_ENABLE_REQ		= 1,  	BFI_IOC_H2I_DISABLE_REQ		= 2, @@ -204,8 +253,8 @@ enum bfi_ioc_i2h_msgs {  	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),  	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),  	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3), -	BFI_IOC_I2H_READY_EVENT		= BFA_I2HM(4), -	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5), +	BFI_IOC_I2H_HBEAT		= BFA_I2HM(4), +	BFI_IOC_I2H_ACQ_ADDR_REPLY	= BFA_I2HM(5),  };  /* @@ -216,11 +265,13 @@ struct bfi_ioc_getattr_req_s {  	union bfi_addr_u	attr_addr;  }; +#define BFI_IOC_ATTR_UUID_SZ	16  struct bfi_ioc_attr_s {  	wwn_t		mfg_pwwn;	/*  Mfg port wwn	   */  	wwn_t		mfg_nwwn;	/*  Mfg node wwn	   */  	mac_t		mfg_mac;	/*  Mfg mac		   */ -	u16	rsvd_a; +	u8		port_mode;	/* bfi_port_mode	   */ +	u8		rsvd_a;  	wwn_t		pwwn;  	wwn_t		nwwn;  	mac_t		mac;		/*  PBC or Mfg mac	   */ @@ -240,6 +291,10 @@ struct bfi_ioc_attr_s {  	char		optrom_version[BFA_VERSION_LEN];  	struct		bfa_mfg_vpd_s	vpd;  	u32	card_type;	/*  card type			*/ +	u8	mfg_day;	/* manufacturing day */ +	u8	mfg_month;	/* manufacturing month */ +	u16	mfg_year;	/* manufacturing year */ +	u8	uuid[BFI_IOC_ATTR_UUID_SZ];	/*!< chinook uuid */  };  /* @@ -270,23 +325,71 @@ struct bfi_ioc_getattr_reply_s {  #define BFI_IOC_TRC_ENTS	256  #define BFI_IOC_FW_SIGNATURE	(0xbfadbfad) +#define BFA_IOC_FW_INV_SIGN	(0xdeaddead)  #define BFI_IOC_MD5SUM_SZ	4 + +struct bfi_ioc_fwver_s { +#ifdef __BIG_ENDIAN +	uint8_t patch; +	uint8_t maint; +	uint8_t minor; +	uint8_t major; +	uint8_t rsvd[2]; +	uint8_t build; +	uint8_t phase; +#else +	uint8_t major; +	uint8_t minor; +	uint8_t maint; +	uint8_t patch; +	uint8_t phase; +	uint8_t build; +	uint8_t rsvd[2]; +#endif +}; +  struct bfi_ioc_image_hdr_s { -	u32	signature;	/*  constant signature */ -	u32	rsvd_a; -	u32	exec;		/*  exec vector	*/ -	u32	param;		/*  parameters		*/ -	u32	rsvd_b[4]; +	u32	signature;	/* constant signature		*/ +	u8	asic_gen;	/* asic generation		*/ +	u8	asic_mode; +	u8	port0_mode;	/* device mode for port 0	*/ +	u8	port1_mode;	/* device mode for port 1	*/ +	u32	exec;		/* exec vector			*/ +	u32	bootenv;	/* fimware boot env		*/ +	u32	rsvd_b[2]; +	struct bfi_ioc_fwver_s	fwver;  	u32	md5sum[BFI_IOC_MD5SUM_SZ];  }; -/* - *  BFI_IOC_I2H_READY_EVENT message - */ -struct bfi_ioc_rdy_event_s { -	struct bfi_mhdr_s	mh;		/*  common msg header */ -	u8			init_status;	/*  init event status */ -	u8			rsvd[3]; +enum bfi_ioc_img_ver_cmp_e { +	BFI_IOC_IMG_VER_INCOMP, +	BFI_IOC_IMG_VER_OLD, +	BFI_IOC_IMG_VER_SAME, +	BFI_IOC_IMG_VER_BETTER +}; + +#define BFI_FWBOOT_DEVMODE_OFF		4 +#define BFI_FWBOOT_TYPE_OFF		8 +#define BFI_FWBOOT_ENV_OFF		12 +#define BFI_FWBOOT_DEVMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \ +	(((u32)(__asic_gen)) << 24 |		\ +	 ((u32)(__asic_mode)) << 16 |		\ +	 ((u32)(__p0_mode)) << 8 |		\ +	 ((u32)(__p1_mode))) + +enum bfi_fwboot_type { +	BFI_FWBOOT_TYPE_NORMAL  = 0, +	BFI_FWBOOT_TYPE_FLASH   = 1, +	BFI_FWBOOT_TYPE_MEMTEST = 2, +}; + +#define BFI_FWBOOT_TYPE_NORMAL	0 +#define BFI_FWBOOT_TYPE_MEMTEST	2 +#define BFI_FWBOOT_ENV_OS       0 + +enum bfi_port_mode { +	BFI_PORT_MODE_FC	= 1, +	BFI_PORT_MODE_ETH	= 2,  };  struct bfi_ioc_hbeat_s { @@ -310,6 +413,10 @@ enum bfi_ioc_state {  	BFI_IOC_MEMTEST		= 9,	/*  IOC is doing memtest	     */  }; +#define BFA_IOC_CB_JOIN_SH	16 +#define BFA_IOC_CB_FWSTATE_MASK	0x0000ffff +#define BFA_IOC_CB_JOIN_MASK	0xffff0000 +  #define BFI_IOC_ENDIAN_SIG  0x12345678  enum { @@ -345,8 +452,8 @@ enum {   */  struct bfi_ioc_ctrl_req_s {  	struct bfi_mhdr_s	mh; -	u8			ioc_class; -	u8			rsvd[3]; +	u16			clscode; +	u16			rsvd;  	u32		tv_sec;  };  #define bfi_ioc_enable_req_t struct bfi_ioc_ctrl_req_s; @@ -358,7 +465,9 @@ struct bfi_ioc_ctrl_req_s {  struct bfi_ioc_ctrl_reply_s {  	struct bfi_mhdr_s	mh;		/*  Common msg header     */  	u8			status;		/*  enable/disable status */ -	u8			rsvd[3]; +	u8			port_mode;	/*  bfa_mode_s	*/ +	u8			cap_bm;		/*  capability bit mask */ +	u8			rsvd;  };  #define bfi_ioc_enable_reply_t struct bfi_ioc_ctrl_reply_s;  #define bfi_ioc_disable_reply_t struct bfi_ioc_ctrl_reply_s; @@ -380,7 +489,7 @@ union bfi_ioc_h2i_msg_u {   */  union bfi_ioc_i2h_msg_u {  	struct bfi_mhdr_s		mh; -	struct bfi_ioc_rdy_event_s	rdy_event; +	struct bfi_ioc_ctrl_reply_s	fw_event;  	u32			mboxmsg[BFI_IOC_MSGSZ];  }; @@ -393,13 +502,14 @@ union bfi_ioc_i2h_msg_u {  #define BFI_PBC_MAX_BLUNS	8  #define BFI_PBC_MAX_VPORTS	16 +#define BFI_PBC_PORT_DISABLED	2  /*   * PBC boot lun configuration   */  struct bfi_pbc_blun_s {  	wwn_t		tgt_pwwn; -	lun_t		tgt_lun; +	struct scsi_lun	tgt_lun;  };  /* @@ -574,6 +684,641 @@ union bfi_port_i2h_msg_u {  	struct bfi_port_generic_rsp_s   clearstats_rsp;  }; +/* + *---------------------------------------------------------------------- + *				ABLK + *---------------------------------------------------------------------- + */ +enum bfi_ablk_h2i_msgs_e { +	BFI_ABLK_H2I_QUERY		= 1, +	BFI_ABLK_H2I_ADPT_CONFIG	= 2, +	BFI_ABLK_H2I_PORT_CONFIG	= 3, +	BFI_ABLK_H2I_PF_CREATE		= 4, +	BFI_ABLK_H2I_PF_DELETE		= 5, +	BFI_ABLK_H2I_PF_UPDATE		= 6, +	BFI_ABLK_H2I_OPTROM_ENABLE	= 7, +	BFI_ABLK_H2I_OPTROM_DISABLE	= 8, +}; + +enum bfi_ablk_i2h_msgs_e { +	BFI_ABLK_I2H_QUERY		= BFA_I2HM(BFI_ABLK_H2I_QUERY), +	BFI_ABLK_I2H_ADPT_CONFIG	= BFA_I2HM(BFI_ABLK_H2I_ADPT_CONFIG), +	BFI_ABLK_I2H_PORT_CONFIG	= BFA_I2HM(BFI_ABLK_H2I_PORT_CONFIG), +	BFI_ABLK_I2H_PF_CREATE		= BFA_I2HM(BFI_ABLK_H2I_PF_CREATE), +	BFI_ABLK_I2H_PF_DELETE		= BFA_I2HM(BFI_ABLK_H2I_PF_DELETE), +	BFI_ABLK_I2H_PF_UPDATE		= BFA_I2HM(BFI_ABLK_H2I_PF_UPDATE), +	BFI_ABLK_I2H_OPTROM_ENABLE	= BFA_I2HM(BFI_ABLK_H2I_OPTROM_ENABLE), +	BFI_ABLK_I2H_OPTROM_DISABLE	= BFA_I2HM(BFI_ABLK_H2I_OPTROM_DISABLE), +}; + +/* BFI_ABLK_H2I_QUERY */ +struct bfi_ablk_h2i_query_s { +	struct bfi_mhdr_s	mh; +	union bfi_addr_u	addr; +}; + +/* BFI_ABL_H2I_ADPT_CONFIG, BFI_ABLK_H2I_PORT_CONFIG */ +struct bfi_ablk_h2i_cfg_req_s { +	struct bfi_mhdr_s	mh; +	u8			mode; +	u8			port; +	u8			max_pf; +	u8			max_vf; +}; + +/* + * BFI_ABLK_H2I_PF_CREATE, BFI_ABLK_H2I_PF_DELETE, + */ +struct bfi_ablk_h2i_pf_req_s { +	struct bfi_mhdr_s	mh; +	u8			pcifn; +	u8			port; +	u16			pers; +	u16			bw_min; /* percent BW @ max speed */ +	u16			bw_max; /* percent BW @ max speed */ +}; + +/* BFI_ABLK_H2I_OPTROM_ENABLE, BFI_ABLK_H2I_OPTROM_DISABLE */ +struct bfi_ablk_h2i_optrom_s { +	struct bfi_mhdr_s	mh; +}; + +/* + * BFI_ABLK_I2H_QUERY + * BFI_ABLK_I2H_PORT_CONFIG + * BFI_ABLK_I2H_PF_CREATE + * BFI_ABLK_I2H_PF_DELETE + * BFI_ABLK_I2H_PF_UPDATE + * BFI_ABLK_I2H_OPTROM_ENABLE + * BFI_ABLK_I2H_OPTROM_DISABLE + */ +struct bfi_ablk_i2h_rsp_s { +	struct bfi_mhdr_s	mh; +	u8			status; +	u8			pcifn; +	u8			port_mode; +}; + + +/* + *	CEE module specific messages + */ + +/* Mailbox commands from host to firmware */ +enum bfi_cee_h2i_msgs_e { +	BFI_CEE_H2I_GET_CFG_REQ = 1, +	BFI_CEE_H2I_RESET_STATS = 2, +	BFI_CEE_H2I_GET_STATS_REQ = 3, +}; + +enum bfi_cee_i2h_msgs_e { +	BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1), +	BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2), +	BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3), +}; + +/* + * H2I command structure for resetting the stats + */ +struct bfi_cee_reset_stats_s { +	struct bfi_mhdr_s  mh; +}; + +/* + * Get configuration  command from host + */ +struct bfi_cee_get_req_s { +	struct bfi_mhdr_s	mh; +	union bfi_addr_u	dma_addr; +}; + +/* + * Reply message from firmware + */ +struct bfi_cee_get_rsp_s { +	struct bfi_mhdr_s	mh; +	u8			cmd_status; +	u8			rsvd[3]; +}; + +/* + * Reply message from firmware + */ +struct bfi_cee_stats_rsp_s { +	struct bfi_mhdr_s	mh; +	u8			cmd_status; +	u8			rsvd[3]; +}; + +/* Mailbox message structures from firmware to host	*/ +union bfi_cee_i2h_msg_u { +	struct bfi_mhdr_s		mh; +	struct bfi_cee_get_rsp_s	get_rsp; +	struct bfi_cee_stats_rsp_s	stats_rsp; +}; + +/* + * SFP related + */ + +enum bfi_sfp_h2i_e { +	BFI_SFP_H2I_SHOW	= 1, +	BFI_SFP_H2I_SCN		= 2, +}; + +enum bfi_sfp_i2h_e { +	BFI_SFP_I2H_SHOW = BFA_I2HM(BFI_SFP_H2I_SHOW), +	BFI_SFP_I2H_SCN	 = BFA_I2HM(BFI_SFP_H2I_SCN), +}; + +/* + *	SFP state change notification + */ +struct bfi_sfp_scn_s { +	struct bfi_mhdr_s mhr;	/* host msg header        */ +	u8	event; +	u8	sfpid; +	u8	pomlvl;	/* pom level: normal/warning/alarm */ +	u8	is_elb;	/* e-loopback */ +}; + +/* + *	SFP state + */ +enum bfa_sfp_stat_e { +	BFA_SFP_STATE_INIT	= 0,	/* SFP state is uninit	*/ +	BFA_SFP_STATE_REMOVED	= 1,	/* SFP is removed	*/ +	BFA_SFP_STATE_INSERTED	= 2,	/* SFP is inserted	*/ +	BFA_SFP_STATE_VALID	= 3,	/* SFP is valid		*/ +	BFA_SFP_STATE_UNSUPPORT	= 4,	/* SFP is unsupport	*/ +	BFA_SFP_STATE_FAILED	= 5,	/* SFP i2c read fail	*/ +}; + +/* + *  SFP memory access type + */ +enum bfi_sfp_mem_e { +	BFI_SFP_MEM_ALL		= 0x1,  /* access all data field */ +	BFI_SFP_MEM_DIAGEXT	= 0x2,  /* access diag ext data field only */ +}; + +struct bfi_sfp_req_s { +	struct bfi_mhdr_s	mh; +	u8			memtype; +	u8			rsvd[3]; +	struct bfi_alen_s	alen; +}; + +struct bfi_sfp_rsp_s { +	struct bfi_mhdr_s	mh; +	u8			status; +	u8			state; +	u8			rsvd[2]; +}; + +/* + *	FLASH module specific + */ +enum bfi_flash_h2i_msgs { +	BFI_FLASH_H2I_QUERY_REQ = 1, +	BFI_FLASH_H2I_ERASE_REQ = 2, +	BFI_FLASH_H2I_WRITE_REQ = 3, +	BFI_FLASH_H2I_READ_REQ = 4, +	BFI_FLASH_H2I_BOOT_VER_REQ = 5, +}; + +enum bfi_flash_i2h_msgs { +	BFI_FLASH_I2H_QUERY_RSP = BFA_I2HM(1), +	BFI_FLASH_I2H_ERASE_RSP = BFA_I2HM(2), +	BFI_FLASH_I2H_WRITE_RSP = BFA_I2HM(3), +	BFI_FLASH_I2H_READ_RSP = BFA_I2HM(4), +	BFI_FLASH_I2H_BOOT_VER_RSP = BFA_I2HM(5), +	BFI_FLASH_I2H_EVENT = BFA_I2HM(127), +}; + +/* + * Flash query request + */ +struct bfi_flash_query_req_s { +	struct bfi_mhdr_s mh;	/* Common msg header */ +	struct bfi_alen_s alen; +}; + +/* + * Flash erase request + */ +struct bfi_flash_erase_req_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u32	type;	/* partition type */ +	u8	instance; /* partition instance */ +	u8	rsv[3]; +}; + +/* + * Flash write request + */ +struct bfi_flash_write_req_s { +	struct bfi_mhdr_s mh;	/* Common msg header */ +	struct bfi_alen_s alen; +	u32	type;	/* partition type */ +	u8	instance; /* partition instance */ +	u8	last; +	u8	rsv[2]; +	u32	offset; +	u32	length; +}; + +/* + * Flash read request + */ +struct bfi_flash_read_req_s { +	struct bfi_mhdr_s mh;	/* Common msg header */ +	u32	type;		/* partition type */ +	u8	instance;	/* partition instance */ +	u8	rsv[3]; +	u32	offset; +	u32	length; +	struct bfi_alen_s alen; +}; + +/* + * Flash query response + */ +struct bfi_flash_query_rsp_s { +	struct bfi_mhdr_s mh;	/* Common msg header */ +	u32	status; +}; + +/* + * Flash read response + */ +struct bfi_flash_read_rsp_s { +	struct bfi_mhdr_s mh;	/* Common msg header */ +	u32	type;       /* partition type */ +	u8	instance;   /* partition instance */ +	u8	rsv[3]; +	u32	status; +	u32	length; +}; + +/* + * Flash write response + */ +struct bfi_flash_write_rsp_s { +	struct bfi_mhdr_s mh;	/* Common msg header */ +	u32	type;       /* partition type */ +	u8	instance;   /* partition instance */ +	u8	rsv[3]; +	u32	status; +	u32	length; +}; + +/* + * Flash erase response + */ +struct bfi_flash_erase_rsp_s { +	struct bfi_mhdr_s mh;	/* Common msg header */ +	u32	type;		/* partition type */ +	u8	instance;	/* partition instance */ +	u8	rsv[3]; +	u32	status; +}; + +/* + * Flash event notification + */ +struct bfi_flash_event_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	bfa_status_t		status; +	u32			param; +}; + +/* + *---------------------------------------------------------------------- + *				DIAG + *---------------------------------------------------------------------- + */ +enum bfi_diag_h2i { +	BFI_DIAG_H2I_PORTBEACON = 1, +	BFI_DIAG_H2I_LOOPBACK = 2, +	BFI_DIAG_H2I_FWPING = 3, +	BFI_DIAG_H2I_TEMPSENSOR = 4, +	BFI_DIAG_H2I_LEDTEST = 5, +	BFI_DIAG_H2I_QTEST      = 6, +	BFI_DIAG_H2I_DPORT	= 7, +}; + +enum bfi_diag_i2h { +	BFI_DIAG_I2H_PORTBEACON = BFA_I2HM(BFI_DIAG_H2I_PORTBEACON), +	BFI_DIAG_I2H_LOOPBACK = BFA_I2HM(BFI_DIAG_H2I_LOOPBACK), +	BFI_DIAG_I2H_FWPING = BFA_I2HM(BFI_DIAG_H2I_FWPING), +	BFI_DIAG_I2H_TEMPSENSOR = BFA_I2HM(BFI_DIAG_H2I_TEMPSENSOR), +	BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST), +	BFI_DIAG_I2H_QTEST      = BFA_I2HM(BFI_DIAG_H2I_QTEST), +	BFI_DIAG_I2H_DPORT	= BFA_I2HM(BFI_DIAG_H2I_DPORT), +	BFI_DIAG_I2H_DPORT_SCN	= BFA_I2HM(8), +}; + +#define BFI_DIAG_MAX_SGES	2 +#define BFI_DIAG_DMA_BUF_SZ	(2 * 1024) +#define BFI_BOOT_MEMTEST_RES_ADDR 0x900 +#define BFI_BOOT_MEMTEST_RES_SIG  0xA0A1A2A3 + +struct bfi_diag_lb_req_s { +	struct bfi_mhdr_s mh; +	u32	loopcnt; +	u32	pattern; +	u8	lb_mode;        /*!< bfa_port_opmode_t */ +	u8	speed;          /*!< bfa_port_speed_t */ +	u8	rsvd[2]; +}; + +struct bfi_diag_lb_rsp_s { +	struct bfi_mhdr_s  mh;          /* 4 bytes */ +	struct bfa_diag_loopback_result_s res; /* 16 bytes */ +}; + +struct bfi_diag_fwping_req_s { +	struct bfi_mhdr_s mh;	/* 4 bytes */ +	struct bfi_alen_s alen; /* 12 bytes */ +	u32	data;           /* user input data pattern */ +	u32	count;          /* user input dma count */ +	u8	qtag;           /* track CPE vc */ +	u8	rsv[3]; +}; + +struct bfi_diag_fwping_rsp_s { +	struct bfi_mhdr_s  mh;          /* 4 bytes */ +	u32	data;           /* user input data pattern    */ +	u8	qtag;           /* track CPE vc               */ +	u8	dma_status;     /* dma status                 */ +	u8	rsv[2]; +}; + +/* + * Temperature Sensor + */ +struct bfi_diag_ts_req_s { +	struct bfi_mhdr_s mh;	/* 4 bytes */ +	u16	temp;           /* 10-bit A/D value */ +	u16	brd_temp;       /* 9-bit board temp */ +	u8	status; +	u8	ts_junc;        /* show junction tempsensor   */ +	u8	ts_brd;         /* show board tempsensor      */ +	u8	rsv; +}; +#define bfi_diag_ts_rsp_t struct bfi_diag_ts_req_s + +struct bfi_diag_ledtest_req_s { +	struct bfi_mhdr_s  mh;  /* 4 bytes */ +	u8	cmd; +	u8	color; +	u8	portid; +	u8	led;    /* bitmap of LEDs to be tested */ +	u16	freq;   /* no. of blinks every 10 secs */ +	u8	rsv[2]; +}; + +/* notify host led operation is done */ +struct bfi_diag_ledtest_rsp_s { +	struct bfi_mhdr_s  mh;  /* 4 bytes */ +}; + +struct bfi_diag_portbeacon_req_s { +	struct bfi_mhdr_s  mh;  /* 4 bytes */ +	u32	period; /* beaconing period */ +	u8	beacon; /* 1: beacon on */ +	u8	rsvd[3]; +}; + +/* notify host the beacon is off */ +struct bfi_diag_portbeacon_rsp_s { +	struct bfi_mhdr_s  mh;  /* 4 bytes */ +}; + +struct bfi_diag_qtest_req_s { +	struct bfi_mhdr_s	mh;             /* 4 bytes */ +	u32	data[BFI_LMSG_PL_WSZ]; /* fill up tcm prefetch area */ +}; +#define bfi_diag_qtest_rsp_t struct bfi_diag_qtest_req_s + +/* + *	D-port test + */ +enum bfi_dport_req { +	BFI_DPORT_DISABLE	= 0,	/* disable dport request	*/ +	BFI_DPORT_ENABLE	= 1,	/* enable dport request		*/ +	BFI_DPORT_START		= 2,	/* start dport request	*/ +	BFI_DPORT_SHOW		= 3,	/* show dport request	*/ +	BFI_DPORT_DYN_DISABLE	= 4,	/* disable dynamic dport request */ +}; + +enum bfi_dport_scn { +	BFI_DPORT_SCN_TESTSTART		= 1, +	BFI_DPORT_SCN_TESTCOMP		= 2, +	BFI_DPORT_SCN_SFP_REMOVED	= 3, +	BFI_DPORT_SCN_DDPORT_ENABLE	= 4, +	BFI_DPORT_SCN_DDPORT_DISABLE	= 5, +	BFI_DPORT_SCN_FCPORT_DISABLE	= 6, +	BFI_DPORT_SCN_SUBTESTSTART	= 7, +	BFI_DPORT_SCN_TESTSKIP		= 8, +	BFI_DPORT_SCN_DDPORT_DISABLED	= 9, +}; + +struct bfi_diag_dport_req_s { +	struct bfi_mhdr_s	mh;	/* 4 bytes                      */ +	u8			req;	/* request 1: enable 0: disable	*/ +	u8			rsvd[3]; +	u32			lpcnt; +	u32			payload; +}; + +struct bfi_diag_dport_rsp_s { +	struct bfi_mhdr_s	mh;	/* header 4 bytes		*/ +	bfa_status_t		status;	/* reply status			*/ +	wwn_t			pwwn;	/* switch port wwn. 8 bytes	*/ +	wwn_t			nwwn;	/* switch node wwn. 8 bytes	*/ +}; + +struct bfi_diag_dport_scn_teststart_s { +	wwn_t	pwwn;	/* switch port wwn. 8 bytes */ +	wwn_t	nwwn;	/* switch node wwn. 8 bytes */ +	u8	type;	/* bfa_diag_dport_test_type_e */ +	u8	mode;	/* bfa_diag_dport_test_opmode */ +	u8	rsvd[2]; +	u32	numfrm; /* from switch uint in 1M */ +}; + +struct bfi_diag_dport_scn_testcomp_s { +	u8	status; /* bfa_diag_dport_test_status_e */ +	u8	speed;  /* bfa_port_speed_t  */ +	u16	numbuffer; /* from switch  */ +	u8	subtest_status[DPORT_TEST_MAX];  /* 4 bytes */ +	u32	latency;   /* from switch  */ +	u32	distance;  /* from swtich unit in meters  */ +			/* Buffers required to saturate the link */ +	u16	frm_sz;	/* from switch for buf_reqd */ +	u8	rsvd[2]; +}; + +struct bfi_diag_dport_scn_s {		/* max size == RDS_RMESZ	*/ +	struct bfi_mhdr_s	mh;	/* header 4 bytes		*/ +	u8			state;  /* new state			*/ +	u8			rsvd[3]; +	union { +		struct bfi_diag_dport_scn_teststart_s teststart; +		struct bfi_diag_dport_scn_testcomp_s testcomp; +	} info; +}; + +union bfi_diag_dport_msg_u { +	struct bfi_diag_dport_req_s	req; +	struct bfi_diag_dport_rsp_s	rsp; +	struct bfi_diag_dport_scn_s	scn; +}; + +/* + *	PHY module specific + */ +enum bfi_phy_h2i_msgs_e { +	BFI_PHY_H2I_QUERY_REQ = 1, +	BFI_PHY_H2I_STATS_REQ = 2, +	BFI_PHY_H2I_WRITE_REQ = 3, +	BFI_PHY_H2I_READ_REQ = 4, +}; + +enum bfi_phy_i2h_msgs_e { +	BFI_PHY_I2H_QUERY_RSP = BFA_I2HM(1), +	BFI_PHY_I2H_STATS_RSP = BFA_I2HM(2), +	BFI_PHY_I2H_WRITE_RSP = BFA_I2HM(3), +	BFI_PHY_I2H_READ_RSP = BFA_I2HM(4), +}; + +/* + * External PHY query request + */ +struct bfi_phy_query_req_s { +	struct bfi_mhdr_s	mh;             /* Common msg header */ +	u8			instance; +	u8			rsv[3]; +	struct bfi_alen_s	alen; +}; + +/* + * External PHY stats request + */ +struct bfi_phy_stats_req_s { +	struct bfi_mhdr_s	mh;             /* Common msg header */ +	u8			instance; +	u8			rsv[3]; +	struct bfi_alen_s	alen; +}; + +/* + * External PHY write request + */ +struct bfi_phy_write_req_s { +	struct bfi_mhdr_s	mh;             /* Common msg header */ +	u8		instance; +	u8		last; +	u8		rsv[2]; +	u32		offset; +	u32		length; +	struct bfi_alen_s	alen; +}; + +/* + * External PHY read request + */ +struct bfi_phy_read_req_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u8		instance; +	u8		rsv[3]; +	u32		offset; +	u32		length; +	struct bfi_alen_s	alen; +}; + +/* + * External PHY query response + */ +struct bfi_phy_query_rsp_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u32			status; +}; + +/* + * External PHY stats response + */ +struct bfi_phy_stats_rsp_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u32			status; +}; + +/* + * External PHY read response + */ +struct bfi_phy_read_rsp_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u32			status; +	u32		length; +}; + +/* + * External PHY write response + */ +struct bfi_phy_write_rsp_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u32			status; +	u32			length; +}; + +enum bfi_fru_h2i_msgs { +	BFI_FRUVPD_H2I_WRITE_REQ = 1, +	BFI_FRUVPD_H2I_READ_REQ = 2, +	BFI_TFRU_H2I_WRITE_REQ = 3, +	BFI_TFRU_H2I_READ_REQ = 4, +}; + +enum bfi_fru_i2h_msgs { +	BFI_FRUVPD_I2H_WRITE_RSP = BFA_I2HM(1), +	BFI_FRUVPD_I2H_READ_RSP = BFA_I2HM(2), +	BFI_TFRU_I2H_WRITE_RSP = BFA_I2HM(3), +	BFI_TFRU_I2H_READ_RSP = BFA_I2HM(4), +}; + +/* + * FRU write request + */ +struct bfi_fru_write_req_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u8			last; +	u8			rsv_1[3]; +	u8			trfr_cmpl; +	u8			rsv_2[3]; +	u32			offset; +	u32			length; +	struct bfi_alen_s	alen; +}; + +/* + * FRU read request + */ +struct bfi_fru_read_req_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u32			offset; +	u32			length; +	struct bfi_alen_s	alen; +}; + +/* + * FRU response + */ +struct bfi_fru_rsp_s { +	struct bfi_mhdr_s	mh;	/* Common msg header */ +	u32			status; +	u32			length; +};  #pragma pack()  #endif /* __BFI_H__ */ diff --git a/drivers/scsi/bfa/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h deleted file mode 100644 index 6f03ed382c6..00000000000 --- a/drivers/scsi/bfa/bfi_cbreg.h +++ /dev/null @@ -1,304 +0,0 @@ - -/* - * bfi_cbreg.h crossbow host block register definitions - * - * !!! Do not edit. Auto generated. !!! - */ - -#ifndef __BFI_CBREG_H__ -#define __BFI_CBREG_H__ - - -#define HOSTFN0_INT_STATUS               0x00014000 -#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000 -#define __HOSTFN0_INT_STATUS_LVL_SH      20 -#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH) -#define __HOSTFN0_INT_STATUS_P           0x000fffff -#define HOSTFN0_INT_MSK                  0x00014004 -#define HOST_PAGE_NUM_FN0                0x00014008 -#define __HOST_PAGE_NUM_FN               0x000001ff -#define HOSTFN1_INT_STATUS               0x00014100 -#define __HOSTFN1_INT_STAT_LVL_MK        0x00f00000 -#define __HOSTFN1_INT_STAT_LVL_SH        20 -#define __HOSTFN1_INT_STAT_LVL(_v)       ((_v) << __HOSTFN1_INT_STAT_LVL_SH) -#define __HOSTFN1_INT_STAT_P             0x000fffff -#define HOSTFN1_INT_MSK                  0x00014104 -#define HOST_PAGE_NUM_FN1                0x00014108 -#define APP_PLL_400_CTL_REG              0x00014204 -#define __P_400_PLL_LOCK                 0x80000000 -#define __APP_PLL_400_SRAM_USE_100MHZ    0x00100000 -#define __APP_PLL_400_RESET_TIMER_MK     0x000e0000 -#define __APP_PLL_400_RESET_TIMER_SH     17 -#define __APP_PLL_400_RESET_TIMER(_v)    ((_v) << __APP_PLL_400_RESET_TIMER_SH) -#define __APP_PLL_400_LOGIC_SOFT_RESET   0x00010000 -#define __APP_PLL_400_CNTLMT0_1_MK       0x0000c000 -#define __APP_PLL_400_CNTLMT0_1_SH       14 -#define __APP_PLL_400_CNTLMT0_1(_v)      ((_v) << __APP_PLL_400_CNTLMT0_1_SH) -#define __APP_PLL_400_JITLMT0_1_MK       0x00003000 -#define __APP_PLL_400_JITLMT0_1_SH       12 -#define __APP_PLL_400_JITLMT0_1(_v)      ((_v) << __APP_PLL_400_JITLMT0_1_SH) -#define __APP_PLL_400_HREF               0x00000800 -#define __APP_PLL_400_HDIV               0x00000400 -#define __APP_PLL_400_P0_1_MK            0x00000300 -#define __APP_PLL_400_P0_1_SH            8 -#define __APP_PLL_400_P0_1(_v)           ((_v) << __APP_PLL_400_P0_1_SH) -#define __APP_PLL_400_Z0_2_MK            0x000000e0 -#define __APP_PLL_400_Z0_2_SH            5 -#define __APP_PLL_400_Z0_2(_v)           ((_v) << __APP_PLL_400_Z0_2_SH) -#define __APP_PLL_400_RSEL200500         0x00000010 -#define __APP_PLL_400_ENARST             0x00000008 -#define __APP_PLL_400_BYPASS             0x00000004 -#define __APP_PLL_400_LRESETN            0x00000002 -#define __APP_PLL_400_ENABLE             0x00000001 -#define APP_PLL_212_CTL_REG              0x00014208 -#define __P_212_PLL_LOCK                 0x80000000 -#define __APP_PLL_212_RESET_TIMER_MK     0x000e0000 -#define __APP_PLL_212_RESET_TIMER_SH     17 -#define __APP_PLL_212_RESET_TIMER(_v)    ((_v) << __APP_PLL_212_RESET_TIMER_SH) -#define __APP_PLL_212_LOGIC_SOFT_RESET   0x00010000 -#define __APP_PLL_212_CNTLMT0_1_MK       0x0000c000 -#define __APP_PLL_212_CNTLMT0_1_SH       14 -#define __APP_PLL_212_CNTLMT0_1(_v)      ((_v) << __APP_PLL_212_CNTLMT0_1_SH) -#define __APP_PLL_212_JITLMT0_1_MK       0x00003000 -#define __APP_PLL_212_JITLMT0_1_SH       12 -#define __APP_PLL_212_JITLMT0_1(_v)      ((_v) << __APP_PLL_212_JITLMT0_1_SH) -#define __APP_PLL_212_HREF               0x00000800 -#define __APP_PLL_212_HDIV               0x00000400 -#define __APP_PLL_212_P0_1_MK            0x00000300 -#define __APP_PLL_212_P0_1_SH            8 -#define __APP_PLL_212_P0_1(_v)           ((_v) << __APP_PLL_212_P0_1_SH) -#define __APP_PLL_212_Z0_2_MK            0x000000e0 -#define __APP_PLL_212_Z0_2_SH            5 -#define __APP_PLL_212_Z0_2(_v)           ((_v) << __APP_PLL_212_Z0_2_SH) -#define __APP_PLL_212_RSEL200500         0x00000010 -#define __APP_PLL_212_ENARST             0x00000008 -#define __APP_PLL_212_BYPASS             0x00000004 -#define __APP_PLL_212_LRESETN            0x00000002 -#define __APP_PLL_212_ENABLE             0x00000001 -#define HOST_SEM0_REG                    0x00014230 -#define __HOST_SEMAPHORE                 0x00000001 -#define HOST_SEM1_REG                    0x00014234 -#define HOST_SEM2_REG                    0x00014238 -#define HOST_SEM3_REG                    0x0001423c -#define HOST_SEM0_INFO_REG               0x00014240 -#define HOST_SEM1_INFO_REG               0x00014244 -#define HOST_SEM2_INFO_REG               0x00014248 -#define HOST_SEM3_INFO_REG               0x0001424c -#define HOSTFN0_LPU0_CMD_STAT            0x00019000 -#define __HOSTFN0_LPU0_MBOX_INFO_MK      0xfffffffe -#define __HOSTFN0_LPU0_MBOX_INFO_SH      1 -#define __HOSTFN0_LPU0_MBOX_INFO(_v)     ((_v) << __HOSTFN0_LPU0_MBOX_INFO_SH) -#define __HOSTFN0_LPU0_MBOX_CMD_STATUS   0x00000001 -#define LPU0_HOSTFN0_CMD_STAT            0x00019008 -#define __LPU0_HOSTFN0_MBOX_INFO_MK      0xfffffffe -#define __LPU0_HOSTFN0_MBOX_INFO_SH      1 -#define __LPU0_HOSTFN0_MBOX_INFO(_v)     ((_v) << __LPU0_HOSTFN0_MBOX_INFO_SH) -#define __LPU0_HOSTFN0_MBOX_CMD_STATUS   0x00000001 -#define HOSTFN1_LPU1_CMD_STAT            0x00019014 -#define __HOSTFN1_LPU1_MBOX_INFO_MK      0xfffffffe -#define __HOSTFN1_LPU1_MBOX_INFO_SH      1 -#define __HOSTFN1_LPU1_MBOX_INFO(_v)     ((_v) << __HOSTFN1_LPU1_MBOX_INFO_SH) -#define __HOSTFN1_LPU1_MBOX_CMD_STATUS   0x00000001 -#define LPU1_HOSTFN1_CMD_STAT            0x0001901c -#define __LPU1_HOSTFN1_MBOX_INFO_MK      0xfffffffe -#define __LPU1_HOSTFN1_MBOX_INFO_SH      1 -#define __LPU1_HOSTFN1_MBOX_INFO(_v)     ((_v) << __LPU1_HOSTFN1_MBOX_INFO_SH) -#define __LPU1_HOSTFN1_MBOX_CMD_STATUS   0x00000001 -#define CPE_Q0_DEPTH                     0x00010014 -#define CPE_Q0_PI                        0x0001001c -#define CPE_Q0_CI                        0x00010020 -#define CPE_Q1_DEPTH                     0x00010034 -#define CPE_Q1_PI                        0x0001003c -#define CPE_Q1_CI                        0x00010040 -#define CPE_Q2_DEPTH                     0x00010054 -#define CPE_Q2_PI                        0x0001005c -#define CPE_Q2_CI                        0x00010060 -#define CPE_Q3_DEPTH                     0x00010074 -#define CPE_Q3_PI                        0x0001007c -#define CPE_Q3_CI                        0x00010080 -#define CPE_Q4_DEPTH                     0x00010094 -#define CPE_Q4_PI                        0x0001009c -#define CPE_Q4_CI                        0x000100a0 -#define CPE_Q5_DEPTH                     0x000100b4 -#define CPE_Q5_PI                        0x000100bc -#define CPE_Q5_CI                        0x000100c0 -#define CPE_Q6_DEPTH                     0x000100d4 -#define CPE_Q6_PI                        0x000100dc -#define CPE_Q6_CI                        0x000100e0 -#define CPE_Q7_DEPTH                     0x000100f4 -#define CPE_Q7_PI                        0x000100fc -#define CPE_Q7_CI                        0x00010100 -#define RME_Q0_DEPTH                     0x00011014 -#define RME_Q0_PI                        0x0001101c -#define RME_Q0_CI                        0x00011020 -#define RME_Q1_DEPTH                     0x00011034 -#define RME_Q1_PI                        0x0001103c -#define RME_Q1_CI                        0x00011040 -#define RME_Q2_DEPTH                     0x00011054 -#define RME_Q2_PI                        0x0001105c -#define RME_Q2_CI                        0x00011060 -#define RME_Q3_DEPTH                     0x00011074 -#define RME_Q3_PI                        0x0001107c -#define RME_Q3_CI                        0x00011080 -#define RME_Q4_DEPTH                     0x00011094 -#define RME_Q4_PI                        0x0001109c -#define RME_Q4_CI                        0x000110a0 -#define RME_Q5_DEPTH                     0x000110b4 -#define RME_Q5_PI                        0x000110bc -#define RME_Q5_CI                        0x000110c0 -#define RME_Q6_DEPTH                     0x000110d4 -#define RME_Q6_PI                        0x000110dc -#define RME_Q6_CI                        0x000110e0 -#define RME_Q7_DEPTH                     0x000110f4 -#define RME_Q7_PI                        0x000110fc -#define RME_Q7_CI                        0x00011100 -#define PSS_CTL_REG                      0x00018800 -#define __PSS_I2C_CLK_DIV_MK             0x00030000 -#define __PSS_I2C_CLK_DIV_SH             16 -#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH) -#define __PSS_LMEM_INIT_DONE             0x00001000 -#define __PSS_LMEM_RESET                 0x00000200 -#define __PSS_LMEM_INIT_EN               0x00000100 -#define __PSS_LPU1_RESET                 0x00000002 -#define __PSS_LPU0_RESET                 0x00000001 -#define PSS_ERR_STATUS_REG               0x00018810 -#define __PSS_LMEM1_CORR_ERR             0x00000800 -#define __PSS_LMEM0_CORR_ERR             0x00000400 -#define __PSS_LMEM1_UNCORR_ERR           0x00000200 -#define __PSS_LMEM0_UNCORR_ERR           0x00000100 -#define __PSS_BAL_PERR                   0x00000080 -#define __PSS_DIP_IF_ERR                 0x00000040 -#define __PSS_IOH_IF_ERR                 0x00000020 -#define __PSS_TDS_IF_ERR                 0x00000010 -#define __PSS_RDS_IF_ERR                 0x00000008 -#define __PSS_SGM_IF_ERR                 0x00000004 -#define __PSS_LPU1_RAM_ERR               0x00000002 -#define __PSS_LPU0_RAM_ERR               0x00000001 -#define ERR_SET_REG                      0x00018818 -#define __PSS_ERR_STATUS_SET             0x00000fff - - -/* - * These definitions are either in error/missing in spec. Its auto-generated - * from hard coded values in regparse.pl. - */ -#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c -#define __EMPHPOST_AT_4G_SH_FIX          0x00000002 -#define __EMPHPRE_AT_4G_FIX              0x00000003 -#define __SFP_TXRATE_EN_FIX              0x00000100 -#define __SFP_RXRATE_EN_FIX              0x00000080 - - -/* - * These register definitions are auto-generated from hard coded values - * in regparse.pl. - */ -#define HOSTFN0_LPU_MBOX0_0              0x00019200 -#define HOSTFN1_LPU_MBOX0_8              0x00019260 -#define LPU_HOSTFN0_MBOX0_0              0x00019280 -#define LPU_HOSTFN1_MBOX0_8              0x000192e0 - - -/* - * These register mapping definitions are auto-generated from mapping tables - * in regparse.pl. - */ -#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG -#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG -#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG -#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG -#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG - -#define CPE_Q_DEPTH(__n) \ -	(CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH)) -#define CPE_Q_PI(__n) \ -	(CPE_Q0_PI + (__n) * (CPE_Q1_PI - CPE_Q0_PI)) -#define CPE_Q_CI(__n) \ -	(CPE_Q0_CI + (__n) * (CPE_Q1_CI - CPE_Q0_CI)) -#define RME_Q_DEPTH(__n) \ -	(RME_Q0_DEPTH + (__n) * (RME_Q1_DEPTH - RME_Q0_DEPTH)) -#define RME_Q_PI(__n) \ -	(RME_Q0_PI + (__n) * (RME_Q1_PI - RME_Q0_PI)) -#define RME_Q_CI(__n) \ -	(RME_Q0_CI + (__n) * (RME_Q1_CI - RME_Q0_CI)) - -#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q)) -#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q)) -#define CPE_Q_MASK(__q)  ((__q) & 0x3) -#define RME_Q_MASK(__q)  ((__q) & 0x3) - - -/* - * PCI MSI-X vector defines - */ -enum { -    BFA_MSIX_CPE_Q0 = 0, -    BFA_MSIX_CPE_Q1 = 1, -    BFA_MSIX_CPE_Q2 = 2, -    BFA_MSIX_CPE_Q3 = 3, -    BFA_MSIX_CPE_Q4 = 4, -    BFA_MSIX_CPE_Q5 = 5, -    BFA_MSIX_CPE_Q6 = 6, -    BFA_MSIX_CPE_Q7 = 7, -    BFA_MSIX_RME_Q0 = 8, -    BFA_MSIX_RME_Q1 = 9, -    BFA_MSIX_RME_Q2 = 10, -    BFA_MSIX_RME_Q3 = 11, -    BFA_MSIX_RME_Q4 = 12, -    BFA_MSIX_RME_Q5 = 13, -    BFA_MSIX_RME_Q6 = 14, -    BFA_MSIX_RME_Q7 = 15, -    BFA_MSIX_ERR_EMC = 16, -    BFA_MSIX_ERR_LPU0 = 17, -    BFA_MSIX_ERR_LPU1 = 18, -    BFA_MSIX_ERR_PSS = 19, -    BFA_MSIX_MBOX_LPU0 = 20, -    BFA_MSIX_MBOX_LPU1 = 21, -    BFA_MSIX_CB_MAX = 22, -}; - -/* - * And corresponding host interrupt status bit field defines - */ -#define __HFN_INT_CPE_Q0                   0x00000001U -#define __HFN_INT_CPE_Q1                   0x00000002U -#define __HFN_INT_CPE_Q2                   0x00000004U -#define __HFN_INT_CPE_Q3                   0x00000008U -#define __HFN_INT_CPE_Q4                   0x00000010U -#define __HFN_INT_CPE_Q5                   0x00000020U -#define __HFN_INT_CPE_Q6                   0x00000040U -#define __HFN_INT_CPE_Q7                   0x00000080U -#define __HFN_INT_RME_Q0                   0x00000100U -#define __HFN_INT_RME_Q1                   0x00000200U -#define __HFN_INT_RME_Q2                   0x00000400U -#define __HFN_INT_RME_Q3                   0x00000800U -#define __HFN_INT_RME_Q4                   0x00001000U -#define __HFN_INT_RME_Q5                   0x00002000U -#define __HFN_INT_RME_Q6                   0x00004000U -#define __HFN_INT_RME_Q7                   0x00008000U -#define __HFN_INT_ERR_EMC                  0x00010000U -#define __HFN_INT_ERR_LPU0                 0x00020000U -#define __HFN_INT_ERR_LPU1                 0x00040000U -#define __HFN_INT_ERR_PSS                  0x00080000U -#define __HFN_INT_MBOX_LPU0                0x00100000U -#define __HFN_INT_MBOX_LPU1                0x00200000U -#define __HFN_INT_MBOX1_LPU0               0x00400000U -#define __HFN_INT_MBOX1_LPU1               0x00800000U -#define __HFN_INT_CPE_MASK                 0x000000ffU -#define __HFN_INT_RME_MASK                 0x0000ff00U - - -/* - * crossbow memory map. - */ -#define PSS_SMEM_PAGE_START	0x8000 -#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15)) -#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff) - -/* - * End of crossbow memory map - */ - - -#endif /* __BFI_CBREG_H__ */ - diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h deleted file mode 100644 index 62b86a4b0e4..00000000000 --- a/drivers/scsi/bfa/bfi_ctreg.h +++ /dev/null @@ -1,627 +0,0 @@ - -/* - * bfi_ctreg.h catapult host block register definitions - * - * !!! Do not edit. Auto generated. !!! - */ - -#ifndef __BFI_CTREG_H__ -#define __BFI_CTREG_H__ - - -#define HOSTFN0_LPU_MBOX0_0		0x00019200 -#define HOSTFN1_LPU_MBOX0_8		0x00019260 -#define LPU_HOSTFN0_MBOX0_0		0x00019280 -#define LPU_HOSTFN1_MBOX0_8		0x000192e0 -#define HOSTFN2_LPU_MBOX0_0		0x00019400 -#define HOSTFN3_LPU_MBOX0_8		0x00019460 -#define LPU_HOSTFN2_MBOX0_0		0x00019480 -#define LPU_HOSTFN3_MBOX0_8		0x000194e0 -#define HOSTFN0_INT_STATUS		0x00014000 -#define __HOSTFN0_HALT_OCCURRED		0x01000000 -#define __HOSTFN0_INT_STATUS_LVL_MK	0x00f00000 -#define __HOSTFN0_INT_STATUS_LVL_SH	20 -#define __HOSTFN0_INT_STATUS_LVL(_v)	((_v) << __HOSTFN0_INT_STATUS_LVL_SH) -#define __HOSTFN0_INT_STATUS_P_MK	0x000f0000 -#define __HOSTFN0_INT_STATUS_P_SH	16 -#define __HOSTFN0_INT_STATUS_P(_v)	((_v) << __HOSTFN0_INT_STATUS_P_SH) -#define __HOSTFN0_INT_STATUS_F		0x0000ffff -#define HOSTFN0_INT_MSK			0x00014004 -#define HOST_PAGE_NUM_FN0		0x00014008 -#define __HOST_PAGE_NUM_FN		0x000001ff -#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c -#define __MSIX_ERR_INDEX_FN		0x000001ff -#define HOSTFN1_INT_STATUS		0x00014100 -#define __HOSTFN1_HALT_OCCURRED		0x01000000 -#define __HOSTFN1_INT_STATUS_LVL_MK	0x00f00000 -#define __HOSTFN1_INT_STATUS_LVL_SH	20 -#define __HOSTFN1_INT_STATUS_LVL(_v)	((_v) << __HOSTFN1_INT_STATUS_LVL_SH) -#define __HOSTFN1_INT_STATUS_P_MK	0x000f0000 -#define __HOSTFN1_INT_STATUS_P_SH	16 -#define __HOSTFN1_INT_STATUS_P(_v)	((_v) << __HOSTFN1_INT_STATUS_P_SH) -#define __HOSTFN1_INT_STATUS_F		0x0000ffff -#define HOSTFN1_INT_MSK			0x00014104 -#define HOST_PAGE_NUM_FN1		0x00014108 -#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c -#define APP_PLL_425_CTL_REG		0x00014204 -#define __P_425_PLL_LOCK		0x80000000 -#define __APP_PLL_425_SRAM_USE_100MHZ	0x00100000 -#define __APP_PLL_425_RESET_TIMER_MK	0x000e0000 -#define __APP_PLL_425_RESET_TIMER_SH	17 -#define __APP_PLL_425_RESET_TIMER(_v)	((_v) << __APP_PLL_425_RESET_TIMER_SH) -#define __APP_PLL_425_LOGIC_SOFT_RESET	0x00010000 -#define __APP_PLL_425_CNTLMT0_1_MK	0x0000c000 -#define __APP_PLL_425_CNTLMT0_1_SH	14 -#define __APP_PLL_425_CNTLMT0_1(_v)	((_v) << __APP_PLL_425_CNTLMT0_1_SH) -#define __APP_PLL_425_JITLMT0_1_MK	0x00003000 -#define __APP_PLL_425_JITLMT0_1_SH	12 -#define __APP_PLL_425_JITLMT0_1(_v)	((_v) << __APP_PLL_425_JITLMT0_1_SH) -#define __APP_PLL_425_HREF		0x00000800 -#define __APP_PLL_425_HDIV		0x00000400 -#define __APP_PLL_425_P0_1_MK		0x00000300 -#define __APP_PLL_425_P0_1_SH		8 -#define __APP_PLL_425_P0_1(_v)		((_v) << __APP_PLL_425_P0_1_SH) -#define __APP_PLL_425_Z0_2_MK		0x000000e0 -#define __APP_PLL_425_Z0_2_SH		5 -#define __APP_PLL_425_Z0_2(_v)		((_v) << __APP_PLL_425_Z0_2_SH) -#define __APP_PLL_425_RSEL200500	0x00000010 -#define __APP_PLL_425_ENARST		0x00000008 -#define __APP_PLL_425_BYPASS		0x00000004 -#define __APP_PLL_425_LRESETN		0x00000002 -#define __APP_PLL_425_ENABLE		0x00000001 -#define APP_PLL_312_CTL_REG		0x00014208 -#define __P_312_PLL_LOCK		0x80000000 -#define __ENABLE_MAC_AHB_1		0x00800000 -#define __ENABLE_MAC_AHB_0		0x00400000 -#define __ENABLE_MAC_1			0x00200000 -#define __ENABLE_MAC_0			0x00100000 -#define __APP_PLL_312_RESET_TIMER_MK	0x000e0000 -#define __APP_PLL_312_RESET_TIMER_SH	17 -#define __APP_PLL_312_RESET_TIMER(_v)	((_v) << __APP_PLL_312_RESET_TIMER_SH) -#define __APP_PLL_312_LOGIC_SOFT_RESET	0x00010000 -#define __APP_PLL_312_CNTLMT0_1_MK	0x0000c000 -#define __APP_PLL_312_CNTLMT0_1_SH	14 -#define __APP_PLL_312_CNTLMT0_1(_v)	((_v) << __APP_PLL_312_CNTLMT0_1_SH) -#define __APP_PLL_312_JITLMT0_1_MK	0x00003000 -#define __APP_PLL_312_JITLMT0_1_SH	12 -#define __APP_PLL_312_JITLMT0_1(_v)	((_v) << __APP_PLL_312_JITLMT0_1_SH) -#define __APP_PLL_312_HREF		0x00000800 -#define __APP_PLL_312_HDIV		0x00000400 -#define __APP_PLL_312_P0_1_MK		0x00000300 -#define __APP_PLL_312_P0_1_SH		8 -#define __APP_PLL_312_P0_1(_v)		((_v) << __APP_PLL_312_P0_1_SH) -#define __APP_PLL_312_Z0_2_MK		0x000000e0 -#define __APP_PLL_312_Z0_2_SH		5 -#define __APP_PLL_312_Z0_2(_v)		((_v) << __APP_PLL_312_Z0_2_SH) -#define __APP_PLL_312_RSEL200500	0x00000010 -#define __APP_PLL_312_ENARST		0x00000008 -#define __APP_PLL_312_BYPASS		0x00000004 -#define __APP_PLL_312_LRESETN		0x00000002 -#define __APP_PLL_312_ENABLE		0x00000001 -#define MBIST_CTL_REG			0x00014220 -#define __EDRAM_BISTR_START		0x00000004 -#define __MBIST_RESET			0x00000002 -#define __MBIST_START			0x00000001 -#define MBIST_STAT_REG			0x00014224 -#define __EDRAM_BISTR_STATUS		0x00000008 -#define __EDRAM_BISTR_DONE		0x00000004 -#define __MEM_BIT_STATUS		0x00000002 -#define __MBIST_DONE			0x00000001 -#define HOST_SEM0_REG			0x00014230 -#define __HOST_SEMAPHORE		0x00000001 -#define HOST_SEM1_REG			0x00014234 -#define HOST_SEM2_REG			0x00014238 -#define HOST_SEM3_REG			0x0001423c -#define HOST_SEM0_INFO_REG		0x00014240 -#define HOST_SEM1_INFO_REG		0x00014244 -#define HOST_SEM2_INFO_REG		0x00014248 -#define HOST_SEM3_INFO_REG		0x0001424c -#define ETH_MAC_SER_REG			0x00014288 -#define __APP_EMS_CKBUFAMPIN		0x00000020 -#define __APP_EMS_REFCLKSEL		0x00000010 -#define __APP_EMS_CMLCKSEL		0x00000008 -#define __APP_EMS_REFCKBUFEN2		0x00000004 -#define __APP_EMS_REFCKBUFEN1		0x00000002 -#define __APP_EMS_CHANNEL_SEL		0x00000001 -#define HOSTFN2_INT_STATUS		0x00014300 -#define __HOSTFN2_HALT_OCCURRED		0x01000000 -#define __HOSTFN2_INT_STATUS_LVL_MK	0x00f00000 -#define __HOSTFN2_INT_STATUS_LVL_SH	20 -#define __HOSTFN2_INT_STATUS_LVL(_v)	((_v) << __HOSTFN2_INT_STATUS_LVL_SH) -#define __HOSTFN2_INT_STATUS_P_MK	0x000f0000 -#define __HOSTFN2_INT_STATUS_P_SH	16 -#define __HOSTFN2_INT_STATUS_P(_v)	((_v) << __HOSTFN2_INT_STATUS_P_SH) -#define __HOSTFN2_INT_STATUS_F		0x0000ffff -#define HOSTFN2_INT_MSK			0x00014304 -#define HOST_PAGE_NUM_FN2		0x00014308 -#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c -#define HOSTFN3_INT_STATUS		0x00014400 -#define __HALT_OCCURRED			0x01000000 -#define __HOSTFN3_INT_STATUS_LVL_MK	0x00f00000 -#define __HOSTFN3_INT_STATUS_LVL_SH	20 -#define __HOSTFN3_INT_STATUS_LVL(_v)	((_v) << __HOSTFN3_INT_STATUS_LVL_SH) -#define __HOSTFN3_INT_STATUS_P_MK	0x000f0000 -#define __HOSTFN3_INT_STATUS_P_SH	16 -#define __HOSTFN3_INT_STATUS_P(_v)	((_v) << __HOSTFN3_INT_STATUS_P_SH) -#define __HOSTFN3_INT_STATUS_F		0x0000ffff -#define HOSTFN3_INT_MSK			0x00014404 -#define HOST_PAGE_NUM_FN3		0x00014408 -#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c -#define FNC_ID_REG			0x00014600 -#define __FUNCTION_NUMBER		0x00000007 -#define FNC_PERS_REG			0x00014604 -#define __F3_FUNCTION_ACTIVE		0x80000000 -#define __F3_FUNCTION_MODE		0x40000000 -#define __F3_PORT_MAP_MK		0x30000000 -#define __F3_PORT_MAP_SH		28 -#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH) -#define __F3_VM_MODE			0x08000000 -#define __F3_INTX_STATUS_MK		0x07000000 -#define __F3_INTX_STATUS_SH		24 -#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH) -#define __F2_FUNCTION_ACTIVE		0x00800000 -#define __F2_FUNCTION_MODE		0x00400000 -#define __F2_PORT_MAP_MK		0x00300000 -#define __F2_PORT_MAP_SH		20 -#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH) -#define __F2_VM_MODE			0x00080000 -#define __F2_INTX_STATUS_MK		0x00070000 -#define __F2_INTX_STATUS_SH		16 -#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH) -#define __F1_FUNCTION_ACTIVE		0x00008000 -#define __F1_FUNCTION_MODE		0x00004000 -#define __F1_PORT_MAP_MK		0x00003000 -#define __F1_PORT_MAP_SH		12 -#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH) -#define __F1_VM_MODE			0x00000800 -#define __F1_INTX_STATUS_MK		0x00000700 -#define __F1_INTX_STATUS_SH		8 -#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH) -#define __F0_FUNCTION_ACTIVE		0x00000080 -#define __F0_FUNCTION_MODE		0x00000040 -#define __F0_PORT_MAP_MK		0x00000030 -#define __F0_PORT_MAP_SH		4 -#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH) -#define __F0_VM_MODE		0x00000008 -#define __F0_INTX_STATUS		0x00000007 -enum { -	__F0_INTX_STATUS_MSIX		= 0x0, -	__F0_INTX_STATUS_INTA		= 0x1, -	__F0_INTX_STATUS_INTB		= 0x2, -	__F0_INTX_STATUS_INTC		= 0x3, -	__F0_INTX_STATUS_INTD		= 0x4, -}; -#define OP_MODE				0x0001460c -#define __APP_ETH_CLK_LOWSPEED		0x00000004 -#define __GLOBAL_CORECLK_HALFSPEED	0x00000002 -#define __GLOBAL_FCOE_MODE		0x00000001 -#define HOST_SEM4_REG			0x00014610 -#define HOST_SEM5_REG			0x00014614 -#define HOST_SEM6_REG			0x00014618 -#define HOST_SEM7_REG			0x0001461c -#define HOST_SEM4_INFO_REG		0x00014620 -#define HOST_SEM5_INFO_REG		0x00014624 -#define HOST_SEM6_INFO_REG		0x00014628 -#define HOST_SEM7_INFO_REG		0x0001462c -#define HOSTFN0_LPU0_MBOX0_CMD_STAT	0x00019000 -#define __HOSTFN0_LPU0_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN0_LPU0_MBOX0_INFO_SH	1 -#define __HOSTFN0_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH) -#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001 -#define HOSTFN0_LPU1_MBOX0_CMD_STAT	0x00019004 -#define __HOSTFN0_LPU1_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN0_LPU1_MBOX0_INFO_SH	1 -#define __HOSTFN0_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH) -#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001 -#define LPU0_HOSTFN0_MBOX0_CMD_STAT	0x00019008 -#define __LPU0_HOSTFN0_MBOX0_INFO_MK	0xfffffffe -#define __LPU0_HOSTFN0_MBOX0_INFO_SH	1 -#define __LPU0_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH) -#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001 -#define LPU1_HOSTFN0_MBOX0_CMD_STAT	0x0001900c -#define __LPU1_HOSTFN0_MBOX0_INFO_MK	0xfffffffe -#define __LPU1_HOSTFN0_MBOX0_INFO_SH	1 -#define __LPU1_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH) -#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001 -#define HOSTFN1_LPU0_MBOX0_CMD_STAT	0x00019010 -#define __HOSTFN1_LPU0_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN1_LPU0_MBOX0_INFO_SH	1 -#define __HOSTFN1_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH) -#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001 -#define HOSTFN1_LPU1_MBOX0_CMD_STAT	0x00019014 -#define __HOSTFN1_LPU1_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN1_LPU1_MBOX0_INFO_SH	1 -#define __HOSTFN1_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH) -#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001 -#define LPU0_HOSTFN1_MBOX0_CMD_STAT	0x00019018 -#define __LPU0_HOSTFN1_MBOX0_INFO_MK	0xfffffffe -#define __LPU0_HOSTFN1_MBOX0_INFO_SH	1 -#define __LPU0_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH) -#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001 -#define LPU1_HOSTFN1_MBOX0_CMD_STAT	0x0001901c -#define __LPU1_HOSTFN1_MBOX0_INFO_MK	0xfffffffe -#define __LPU1_HOSTFN1_MBOX0_INFO_SH	1 -#define __LPU1_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH) -#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001 -#define HOSTFN2_LPU0_MBOX0_CMD_STAT	0x00019150 -#define __HOSTFN2_LPU0_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN2_LPU0_MBOX0_INFO_SH	1 -#define __HOSTFN2_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH) -#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001 -#define HOSTFN2_LPU1_MBOX0_CMD_STAT	0x00019154 -#define __HOSTFN2_LPU1_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN2_LPU1_MBOX0_INFO_SH	1 -#define __HOSTFN2_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH) -#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001 -#define LPU0_HOSTFN2_MBOX0_CMD_STAT	0x00019158 -#define __LPU0_HOSTFN2_MBOX0_INFO_MK	0xfffffffe -#define __LPU0_HOSTFN2_MBOX0_INFO_SH	1 -#define __LPU0_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH) -#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001 -#define LPU1_HOSTFN2_MBOX0_CMD_STAT	0x0001915c -#define __LPU1_HOSTFN2_MBOX0_INFO_MK	0xfffffffe -#define __LPU1_HOSTFN2_MBOX0_INFO_SH	1 -#define __LPU1_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH) -#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001 -#define HOSTFN3_LPU0_MBOX0_CMD_STAT	0x00019160 -#define __HOSTFN3_LPU0_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN3_LPU0_MBOX0_INFO_SH	1 -#define __HOSTFN3_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH) -#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001 -#define HOSTFN3_LPU1_MBOX0_CMD_STAT	0x00019164 -#define __HOSTFN3_LPU1_MBOX0_INFO_MK	0xfffffffe -#define __HOSTFN3_LPU1_MBOX0_INFO_SH	1 -#define __HOSTFN3_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH) -#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001 -#define LPU0_HOSTFN3_MBOX0_CMD_STAT	0x00019168 -#define __LPU0_HOSTFN3_MBOX0_INFO_MK	0xfffffffe -#define __LPU0_HOSTFN3_MBOX0_INFO_SH	1 -#define __LPU0_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH) -#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001 -#define LPU1_HOSTFN3_MBOX0_CMD_STAT	0x0001916c -#define __LPU1_HOSTFN3_MBOX0_INFO_MK	0xfffffffe -#define __LPU1_HOSTFN3_MBOX0_INFO_SH	1 -#define __LPU1_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH) -#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS	0x00000001 -#define FW_INIT_HALT_P0			0x000191ac -#define __FW_INIT_HALT_P		0x00000001 -#define FW_INIT_HALT_P1			0x000191bc -#define CPE_PI_PTR_Q0			0x00038000 -#define __CPE_PI_UNUSED_MK		0xffff0000 -#define __CPE_PI_UNUSED_SH		16 -#define __CPE_PI_UNUSED(_v)		((_v) << __CPE_PI_UNUSED_SH) -#define __CPE_PI_PTR			0x0000ffff -#define CPE_PI_PTR_Q1			0x00038040 -#define CPE_CI_PTR_Q0			0x00038004 -#define __CPE_CI_UNUSED_MK		0xffff0000 -#define __CPE_CI_UNUSED_SH		16 -#define __CPE_CI_UNUSED(_v)		((_v) << __CPE_CI_UNUSED_SH) -#define __CPE_CI_PTR			0x0000ffff -#define CPE_CI_PTR_Q1			0x00038044 -#define CPE_DEPTH_Q0			0x00038008 -#define __CPE_DEPTH_UNUSED_MK		0xf8000000 -#define __CPE_DEPTH_UNUSED_SH		27 -#define __CPE_DEPTH_UNUSED(_v)		((_v) << __CPE_DEPTH_UNUSED_SH) -#define __CPE_MSIX_VEC_INDEX_MK		0x07ff0000 -#define __CPE_MSIX_VEC_INDEX_SH		16 -#define __CPE_MSIX_VEC_INDEX(_v)	((_v) << __CPE_MSIX_VEC_INDEX_SH) -#define __CPE_DEPTH			0x0000ffff -#define CPE_DEPTH_Q1			0x00038048 -#define CPE_QCTRL_Q0			0x0003800c -#define __CPE_CTRL_UNUSED30_MK		0xfc000000 -#define __CPE_CTRL_UNUSED30_SH		26 -#define __CPE_CTRL_UNUSED30(_v)		((_v) << __CPE_CTRL_UNUSED30_SH) -#define __CPE_FUNC_INT_CTRL_MK		0x03000000 -#define __CPE_FUNC_INT_CTRL_SH		24 -#define __CPE_FUNC_INT_CTRL(_v)		((_v) << __CPE_FUNC_INT_CTRL_SH) -enum { -	__CPE_FUNC_INT_CTRL_DISABLE		= 0x0, -	__CPE_FUNC_INT_CTRL_F2NF		= 0x1, -	__CPE_FUNC_INT_CTRL_3QUART		= 0x2, -	__CPE_FUNC_INT_CTRL_HALF		= 0x3, -}; -#define __CPE_CTRL_UNUSED20_MK		0x00f00000 -#define __CPE_CTRL_UNUSED20_SH		20 -#define __CPE_CTRL_UNUSED20(_v)		((_v) << __CPE_CTRL_UNUSED20_SH) -#define __CPE_SCI_TH_MK			0x000f0000 -#define __CPE_SCI_TH_SH			16 -#define __CPE_SCI_TH(_v)		((_v) << __CPE_SCI_TH_SH) -#define __CPE_CTRL_UNUSED10_MK		0x0000c000 -#define __CPE_CTRL_UNUSED10_SH		14 -#define __CPE_CTRL_UNUSED10(_v)		((_v) << __CPE_CTRL_UNUSED10_SH) -#define __CPE_ACK_PENDING		0x00002000 -#define __CPE_CTRL_UNUSED40_MK		0x00001c00 -#define __CPE_CTRL_UNUSED40_SH		10 -#define __CPE_CTRL_UNUSED40(_v)		((_v) << __CPE_CTRL_UNUSED40_SH) -#define __CPE_PCIEID_MK			0x00000300 -#define __CPE_PCIEID_SH			8 -#define __CPE_PCIEID(_v)		((_v) << __CPE_PCIEID_SH) -#define __CPE_CTRL_UNUSED00_MK		0x000000fe -#define __CPE_CTRL_UNUSED00_SH		1 -#define __CPE_CTRL_UNUSED00(_v)		((_v) << __CPE_CTRL_UNUSED00_SH) -#define __CPE_ESIZE			0x00000001 -#define CPE_QCTRL_Q1			0x0003804c -#define __CPE_CTRL_UNUSED31_MK		0xfc000000 -#define __CPE_CTRL_UNUSED31_SH		26 -#define __CPE_CTRL_UNUSED31(_v)		((_v) << __CPE_CTRL_UNUSED31_SH) -#define __CPE_CTRL_UNUSED21_MK		0x00f00000 -#define __CPE_CTRL_UNUSED21_SH		20 -#define __CPE_CTRL_UNUSED21(_v)		((_v) << __CPE_CTRL_UNUSED21_SH) -#define __CPE_CTRL_UNUSED11_MK		0x0000c000 -#define __CPE_CTRL_UNUSED11_SH		14 -#define __CPE_CTRL_UNUSED11(_v)		((_v) << __CPE_CTRL_UNUSED11_SH) -#define __CPE_CTRL_UNUSED41_MK		0x00001c00 -#define __CPE_CTRL_UNUSED41_SH		10 -#define __CPE_CTRL_UNUSED41(_v)		((_v) << __CPE_CTRL_UNUSED41_SH) -#define __CPE_CTRL_UNUSED01_MK		0x000000fe -#define __CPE_CTRL_UNUSED01_SH		1 -#define __CPE_CTRL_UNUSED01(_v)		((_v) << __CPE_CTRL_UNUSED01_SH) -#define RME_PI_PTR_Q0			0x00038020 -#define __LATENCY_TIME_STAMP_MK		0xffff0000 -#define __LATENCY_TIME_STAMP_SH		16 -#define __LATENCY_TIME_STAMP(_v)	((_v) << __LATENCY_TIME_STAMP_SH) -#define __RME_PI_PTR			0x0000ffff -#define RME_PI_PTR_Q1			0x00038060 -#define RME_CI_PTR_Q0			0x00038024 -#define __DELAY_TIME_STAMP_MK		0xffff0000 -#define __DELAY_TIME_STAMP_SH		16 -#define __DELAY_TIME_STAMP(_v)		((_v) << __DELAY_TIME_STAMP_SH) -#define __RME_CI_PTR			0x0000ffff -#define RME_CI_PTR_Q1			0x00038064 -#define RME_DEPTH_Q0			0x00038028 -#define __RME_DEPTH_UNUSED_MK		0xf8000000 -#define __RME_DEPTH_UNUSED_SH		27 -#define __RME_DEPTH_UNUSED(_v)		((_v) << __RME_DEPTH_UNUSED_SH) -#define __RME_MSIX_VEC_INDEX_MK		0x07ff0000 -#define __RME_MSIX_VEC_INDEX_SH		16 -#define __RME_MSIX_VEC_INDEX(_v)	((_v) << __RME_MSIX_VEC_INDEX_SH) -#define __RME_DEPTH			0x0000ffff -#define RME_DEPTH_Q1			0x00038068 -#define RME_QCTRL_Q0			0x0003802c -#define __RME_INT_LATENCY_TIMER_MK	0xff000000 -#define __RME_INT_LATENCY_TIMER_SH	24 -#define __RME_INT_LATENCY_TIMER(_v)	((_v) << __RME_INT_LATENCY_TIMER_SH) -#define __RME_INT_DELAY_TIMER_MK	0x00ff0000 -#define __RME_INT_DELAY_TIMER_SH	16 -#define __RME_INT_DELAY_TIMER(_v)	((_v) << __RME_INT_DELAY_TIMER_SH) -#define __RME_INT_DELAY_DISABLE		0x00008000 -#define __RME_DLY_DELAY_DISABLE		0x00004000 -#define __RME_ACK_PENDING		0x00002000 -#define __RME_FULL_INTERRUPT_DISABLE	0x00001000 -#define __RME_CTRL_UNUSED10_MK		0x00000c00 -#define __RME_CTRL_UNUSED10_SH		10 -#define __RME_CTRL_UNUSED10(_v)		((_v) << __RME_CTRL_UNUSED10_SH) -#define __RME_PCIEID_MK			0x00000300 -#define __RME_PCIEID_SH			8 -#define __RME_PCIEID(_v)		((_v) << __RME_PCIEID_SH) -#define __RME_CTRL_UNUSED00_MK		0x000000fe -#define __RME_CTRL_UNUSED00_SH		1 -#define __RME_CTRL_UNUSED00(_v)		((_v) << __RME_CTRL_UNUSED00_SH) -#define __RME_ESIZE			0x00000001 -#define RME_QCTRL_Q1			0x0003806c -#define __RME_CTRL_UNUSED11_MK		0x00000c00 -#define __RME_CTRL_UNUSED11_SH		10 -#define __RME_CTRL_UNUSED11(_v)		((_v) << __RME_CTRL_UNUSED11_SH) -#define __RME_CTRL_UNUSED01_MK		0x000000fe -#define __RME_CTRL_UNUSED01_SH		1 -#define __RME_CTRL_UNUSED01(_v)		((_v) << __RME_CTRL_UNUSED01_SH) -#define PSS_CTL_REG			0x00018800 -#define __PSS_I2C_CLK_DIV_MK		0x007f0000 -#define __PSS_I2C_CLK_DIV_SH		16 -#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH) -#define __PSS_LMEM_INIT_DONE		0x00001000 -#define __PSS_LMEM_RESET		0x00000200 -#define __PSS_LMEM_INIT_EN		0x00000100 -#define __PSS_LPU1_RESET		0x00000002 -#define __PSS_LPU0_RESET		0x00000001 -#define PSS_ERR_STATUS_REG		0x00018810 -#define __PSS_LPU1_TCM_READ_ERR		0x00200000 -#define __PSS_LPU0_TCM_READ_ERR		0x00100000 -#define __PSS_LMEM5_CORR_ERR		0x00080000 -#define __PSS_LMEM4_CORR_ERR		0x00040000 -#define __PSS_LMEM3_CORR_ERR		0x00020000 -#define __PSS_LMEM2_CORR_ERR		0x00010000 -#define __PSS_LMEM1_CORR_ERR		0x00008000 -#define __PSS_LMEM0_CORR_ERR		0x00004000 -#define __PSS_LMEM5_UNCORR_ERR		0x00002000 -#define __PSS_LMEM4_UNCORR_ERR		0x00001000 -#define __PSS_LMEM3_UNCORR_ERR		0x00000800 -#define __PSS_LMEM2_UNCORR_ERR		0x00000400 -#define __PSS_LMEM1_UNCORR_ERR		0x00000200 -#define __PSS_LMEM0_UNCORR_ERR		0x00000100 -#define __PSS_BAL_PERR			0x00000080 -#define __PSS_DIP_IF_ERR		0x00000040 -#define __PSS_IOH_IF_ERR		0x00000020 -#define __PSS_TDS_IF_ERR		0x00000010 -#define __PSS_RDS_IF_ERR		0x00000008 -#define __PSS_SGM_IF_ERR		0x00000004 -#define __PSS_LPU1_RAM_ERR		0x00000002 -#define __PSS_LPU0_RAM_ERR		0x00000001 -#define ERR_SET_REG			0x00018818 -#define __PSS_ERR_STATUS_SET		0x003fffff -#define PMM_1T_RESET_REG_P0		0x0002381c -#define __PMM_1T_RESET_P		0x00000001 -#define PMM_1T_RESET_REG_P1		0x00023c1c -#define HQM_QSET0_RXQ_DRBL_P0		0x00038000 -#define __RXQ0_ADD_VECTORS_P		0x80000000 -#define __RXQ0_STOP_P			0x40000000 -#define __RXQ0_PRD_PTR_P		0x0000ffff -#define HQM_QSET1_RXQ_DRBL_P0		0x00038080 -#define __RXQ1_ADD_VECTORS_P		0x80000000 -#define __RXQ1_STOP_P			0x40000000 -#define __RXQ1_PRD_PTR_P		0x0000ffff -#define HQM_QSET0_RXQ_DRBL_P1		0x0003c000 -#define HQM_QSET1_RXQ_DRBL_P1		0x0003c080 -#define HQM_QSET0_TXQ_DRBL_P0		0x00038020 -#define __TXQ0_ADD_VECTORS_P		0x80000000 -#define __TXQ0_STOP_P			0x40000000 -#define __TXQ0_PRD_PTR_P		0x0000ffff -#define HQM_QSET1_TXQ_DRBL_P0		0x000380a0 -#define __TXQ1_ADD_VECTORS_P		0x80000000 -#define __TXQ1_STOP_P			0x40000000 -#define __TXQ1_PRD_PTR_P		0x0000ffff -#define HQM_QSET0_TXQ_DRBL_P1		0x0003c020 -#define HQM_QSET1_TXQ_DRBL_P1		0x0003c0a0 -#define HQM_QSET0_IB_DRBL_1_P0		0x00038040 -#define __IB1_0_ACK_P			0x80000000 -#define __IB1_0_DISABLE_P		0x40000000 -#define __IB1_0_COALESCING_CFG_P_MK	0x00ff0000 -#define __IB1_0_COALESCING_CFG_P_SH	16 -#define __IB1_0_COALESCING_CFG_P(_v)	((_v) << __IB1_0_COALESCING_CFG_P_SH) -#define __IB1_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff -#define HQM_QSET1_IB_DRBL_1_P0		0x000380c0 -#define __IB1_1_ACK_P			0x80000000 -#define __IB1_1_DISABLE_P		0x40000000 -#define __IB1_1_COALESCING_CFG_P_MK	0x00ff0000 -#define __IB1_1_COALESCING_CFG_P_SH	16 -#define __IB1_1_COALESCING_CFG_P(_v)	((_v) << __IB1_1_COALESCING_CFG_P_SH) -#define __IB1_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff -#define HQM_QSET0_IB_DRBL_1_P1		0x0003c040 -#define HQM_QSET1_IB_DRBL_1_P1		0x0003c0c0 -#define HQM_QSET0_IB_DRBL_2_P0		0x00038060 -#define __IB2_0_ACK_P			0x80000000 -#define __IB2_0_DISABLE_P		0x40000000 -#define __IB2_0_COALESCING_CFG_P_MK	0x00ff0000 -#define __IB2_0_COALESCING_CFG_P_SH	16 -#define __IB2_0_COALESCING_CFG_P(_v)	((_v) << __IB2_0_COALESCING_CFG_P_SH) -#define __IB2_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff -#define HQM_QSET1_IB_DRBL_2_P0		0x000380e0 -#define __IB2_1_ACK_P			0x80000000 -#define __IB2_1_DISABLE_P		0x40000000 -#define __IB2_1_COALESCING_CFG_P_MK	0x00ff0000 -#define __IB2_1_COALESCING_CFG_P_SH	16 -#define __IB2_1_COALESCING_CFG_P(_v)	((_v) << __IB2_1_COALESCING_CFG_P_SH) -#define __IB2_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff -#define HQM_QSET0_IB_DRBL_2_P1		0x0003c060 -#define HQM_QSET1_IB_DRBL_2_P1		0x0003c0e0 - - -/* - * These definitions are either in error/missing in spec. Its auto-generated - * from hard coded values in regparse.pl. - */ -#define __EMPHPOST_AT_4G_MK_FIX		0x0000001c -#define __EMPHPOST_AT_4G_SH_FIX		0x00000002 -#define __EMPHPRE_AT_4G_FIX		0x00000003 -#define __SFP_TXRATE_EN_FIX		0x00000100 -#define __SFP_RXRATE_EN_FIX		0x00000080 - - -/* - * These register definitions are auto-generated from hard coded values - * in regparse.pl. - */ - - -/* - * These register mapping definitions are auto-generated from mapping tables - * in regparse.pl. - */ -#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG -#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG -#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG -#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG -#define BFA_FW_USE_COUNT		 HOST_SEM4_INFO_REG - -#define CPE_DEPTH_Q(__n) \ -	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0)) -#define CPE_QCTRL_Q(__n) \ -	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0)) -#define CPE_PI_PTR_Q(__n) \ -	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0)) -#define CPE_CI_PTR_Q(__n) \ -	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0)) -#define RME_DEPTH_Q(__n) \ -	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0)) -#define RME_QCTRL_Q(__n) \ -	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0)) -#define RME_PI_PTR_Q(__n) \ -	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0)) -#define RME_CI_PTR_Q(__n) \ -	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0)) -#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \ -	* (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0)) -#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \ -	* (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0)) -#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \ -	* (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0)) -#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \ -	* (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0)) -#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \ -	* (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1)) -#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \ -	* (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1)) -#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \ -	* (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1)) -#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \ -	* (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1)) - -#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) -#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) -#define CPE_Q_MASK(__q) ((__q) & 0x3) -#define RME_Q_MASK(__q) ((__q) & 0x3) - - -/* - * PCI MSI-X vector defines - */ -enum { -	BFA_MSIX_CPE_Q0 = 0, -	BFA_MSIX_CPE_Q1 = 1, -	BFA_MSIX_CPE_Q2 = 2, -	BFA_MSIX_CPE_Q3 = 3, -	BFA_MSIX_RME_Q0 = 4, -	BFA_MSIX_RME_Q1 = 5, -	BFA_MSIX_RME_Q2 = 6, -	BFA_MSIX_RME_Q3 = 7, -	BFA_MSIX_LPU_ERR = 8, -	BFA_MSIX_CT_MAX = 9, -}; - -/* - * And corresponding host interrupt status bit field defines - */ -#define __HFN_INT_CPE_Q0		0x00000001U -#define __HFN_INT_CPE_Q1		0x00000002U -#define __HFN_INT_CPE_Q2		0x00000004U -#define __HFN_INT_CPE_Q3		0x00000008U -#define __HFN_INT_CPE_Q4		0x00000010U -#define __HFN_INT_CPE_Q5		0x00000020U -#define __HFN_INT_CPE_Q6		0x00000040U -#define __HFN_INT_CPE_Q7		0x00000080U -#define __HFN_INT_RME_Q0		0x00000100U -#define __HFN_INT_RME_Q1		0x00000200U -#define __HFN_INT_RME_Q2		0x00000400U -#define __HFN_INT_RME_Q3		0x00000800U -#define __HFN_INT_RME_Q4		0x00001000U -#define __HFN_INT_RME_Q5		0x00002000U -#define __HFN_INT_RME_Q6		0x00004000U -#define __HFN_INT_RME_Q7		0x00008000U -#define __HFN_INT_ERR_EMC		0x00010000U -#define __HFN_INT_ERR_LPU0		0x00020000U -#define __HFN_INT_ERR_LPU1		0x00040000U -#define __HFN_INT_ERR_PSS		0x00080000U -#define __HFN_INT_MBOX_LPU0		0x00100000U -#define __HFN_INT_MBOX_LPU1		0x00200000U -#define __HFN_INT_MBOX1_LPU0		0x00400000U -#define __HFN_INT_MBOX1_LPU1		0x00800000U -#define __HFN_INT_LL_HALT		0x01000000U -#define __HFN_INT_CPE_MASK		0x000000ffU -#define __HFN_INT_RME_MASK		0x0000ff00U - - -/* - * catapult memory map. - */ -#define LL_PGN_HQM0		0x0096 -#define LL_PGN_HQM1		0x0097 -#define PSS_SMEM_PAGE_START	0x8000 -#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15)) -#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff) - -/* - * End of catapult memory map - */ - - -#endif /* __BFI_CTREG_H__ */ diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h index fa9f6fb9d45..1a3fe5ad58f 100644 --- a/drivers/scsi/bfa/bfi_ms.h +++ b/drivers/scsi/bfa/bfi_ms.h @@ -28,11 +28,15 @@ enum bfi_iocfc_h2i_msgs {  	BFI_IOCFC_H2I_CFG_REQ		= 1,  	BFI_IOCFC_H2I_SET_INTR_REQ	= 2,  	BFI_IOCFC_H2I_UPDATEQ_REQ	= 3, +	BFI_IOCFC_H2I_FAA_QUERY_REQ	= 4, +	BFI_IOCFC_H2I_ADDR_REQ		= 5,  };  enum bfi_iocfc_i2h_msgs {  	BFI_IOCFC_I2H_CFG_REPLY		= BFA_I2HM(1),  	BFI_IOCFC_I2H_UPDATEQ_RSP	= BFA_I2HM(3), +	BFI_IOCFC_I2H_FAA_QUERY_RSP	= BFA_I2HM(4), +	BFI_IOCFC_I2H_ADDR_MSG		= BFA_I2HM(5),  };  struct bfi_iocfc_cfg_s { @@ -40,6 +44,12 @@ struct bfi_iocfc_cfg_s {  	u8	 sense_buf_len;	/*  SCSI sense length	    */  	u16	rsvd_1;  	u32	endian_sig;	/*  endian signature of host     */ +	u8	rsvd_2; +	u8	single_msix_vec; +	u8	rsvd[2]; +	__be16	num_ioim_reqs; +	__be16	num_fwtio_reqs; +  	/*  	 * Request and response circular queue base addresses, size and @@ -47,14 +57,15 @@ struct bfi_iocfc_cfg_s {  	 */  	union bfi_addr_u  req_cq_ba[BFI_IOC_MAX_CQS];  	union bfi_addr_u  req_shadow_ci[BFI_IOC_MAX_CQS]; -	u16    req_cq_elems[BFI_IOC_MAX_CQS]; +	__be16    req_cq_elems[BFI_IOC_MAX_CQS];  	union bfi_addr_u  rsp_cq_ba[BFI_IOC_MAX_CQS];  	union bfi_addr_u  rsp_shadow_pi[BFI_IOC_MAX_CQS]; -	u16    rsp_cq_elems[BFI_IOC_MAX_CQS]; +	__be16    rsp_cq_elems[BFI_IOC_MAX_CQS];  	union bfi_addr_u  stats_addr;	/*  DMA-able address for stats	  */  	union bfi_addr_u  cfgrsp_addr;	/*  config response dma address  */ -	union bfi_addr_u  ioim_snsbase;  /*  IO sense buffer base address */ +	union bfi_addr_u  ioim_snsbase[BFI_IOIM_SNSBUF_SEGS]; +					/*  IO sense buf base addr segments */  	struct bfa_iocfc_intr_attr_s intr_attr; /*  IOC interrupt attributes */  }; @@ -68,11 +79,25 @@ struct bfi_iocfc_bootwwns {  	u8		rsvd[7];  }; +/** + * Queue configuration response from firmware + */ +struct bfi_iocfc_qreg_s { +	u32	cpe_q_ci_off[BFI_IOC_MAX_CQS]; +	u32	cpe_q_pi_off[BFI_IOC_MAX_CQS]; +	u32	cpe_qctl_off[BFI_IOC_MAX_CQS]; +	u32	rme_q_ci_off[BFI_IOC_MAX_CQS]; +	u32	rme_q_pi_off[BFI_IOC_MAX_CQS]; +	u32	rme_qctl_off[BFI_IOC_MAX_CQS]; +	u8	hw_qid[BFI_IOC_MAX_CQS]; +}; +  struct bfi_iocfc_cfgrsp_s {  	struct bfa_iocfc_fwcfg_s	fwcfg;  	struct bfa_iocfc_intr_attr_s	intr_attr;  	struct bfi_iocfc_bootwwns	bootwwns;  	struct bfi_pbc_s		pbc_cfg; +	struct bfi_iocfc_qreg_s		qreg;  };  /* @@ -102,8 +127,8 @@ struct bfi_iocfc_set_intr_req_s {  	struct bfi_mhdr_s mh;		/*  common msg header		*/  	u8		coalesce;	/*  enable intr coalescing	*/  	u8		rsvd[3]; -	u16	delay;		/*  delay timer 0..1125us	*/ -	u16	latency;	/*  latency timer 0..225us	*/ +	__be16	delay;		/*  delay timer 0..1125us	*/ +	__be16	latency;	/*  latency timer 0..225us	*/  }; @@ -150,6 +175,44 @@ union bfi_iocfc_i2h_msg_u {  	u32 mboxmsg[BFI_IOC_MSGSZ];  }; +/* + * BFI_IOCFC_H2I_FAA_ENABLE_REQ BFI_IOCFC_H2I_FAA_DISABLE_REQ message + */ +struct bfi_faa_en_dis_s { +	struct bfi_mhdr_s mh;	/* common msg header    */ +}; + +struct bfi_faa_addr_msg_s { +	struct  bfi_mhdr_s mh;	/* common msg header	*/ +	u8	rsvd[4]; +	wwn_t	pwwn;		/* Fabric acquired PWWN	*/ +	wwn_t	nwwn;		/* Fabric acquired PWWN	*/ +}; + +/* + * BFI_IOCFC_H2I_FAA_QUERY_REQ message + */ +struct bfi_faa_query_s { +	struct bfi_mhdr_s mh;	/* common msg header    */ +	u8	faa_status;	/* FAA status           */ +	u8	addr_source;	/* PWWN source          */ +	u8	rsvd[2]; +	wwn_t	faa;		/* Fabric acquired PWWN	*/ +}; + +/* + * BFI_IOCFC_I2H_FAA_ENABLE_RSP, BFI_IOCFC_I2H_FAA_DISABLE_RSP message + */ +struct bfi_faa_en_dis_rsp_s { +	struct bfi_mhdr_s mh;	/* common msg header    */ +	u8	status;		/* updateq  status      */ +	u8	rsvd[3]; +}; + +/* + * BFI_IOCFC_I2H_FAA_QUERY_RSP message + */ +#define bfi_faa_query_rsp_t struct bfi_faa_query_s  enum bfi_fcport_h2i {  	BFI_FCPORT_H2I_ENABLE_REQ		= (1), @@ -188,7 +251,8 @@ struct bfi_fcport_rsp_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		    */  	u8		   status;	/*  port enable status		    */  	u8		   rsvd[3]; -	u32	   msgtag;	/*  msgtag for reply		    */ +	struct	bfa_port_cfg_s port_cfg;/* port configuration	*/ +	u32	msgtag;			/* msgtag for reply	*/  };  /* @@ -202,7 +266,8 @@ struct bfi_fcport_enable_req_s {  	struct bfa_port_cfg_s port_cfg; /*  port configuration	    */  	union bfi_addr_u   stats_dma_addr; /*  DMA address for stats	    */  	u32	   msgtag;	/*  msgtag for reply		    */ -	u32	   rsvd2; +	u8	use_flash_cfg;	/* get prot cfg from flash */ +	u8	rsvd2[3];  };  /* @@ -210,8 +275,8 @@ struct bfi_fcport_enable_req_s {   */  struct bfi_fcport_set_svc_params_req_s {  	struct bfi_mhdr_s  mh;		/*  msg header */ -	u16	   tx_bbcredit;	/*  Tx credits */ -	u16	   rsvd; +	__be16	   tx_bbcredit;	/*  Tx credits */ +	u8	rsvd[2];  };  /* @@ -231,7 +296,7 @@ struct bfi_fcport_trunk_link_s {  	u8			state;		/* bfa_trunk_link_state_t */  	u8			speed;		/* bfa_port_speed_t */  	u8			rsvd; -	u32		deskew; +	__be32		deskew;  };  #define BFI_FCPORT_MAX_LINKS	2 @@ -284,19 +349,19 @@ enum bfi_fcxp_i2h {   */  struct bfi_fcxp_send_req_s {  	struct bfi_mhdr_s  mh;		/*  Common msg header		    */ -	u16	fcxp_tag;	/*  driver request tag		    */ -	u16	max_frmsz;	/*  max send frame size	    */ -	u16	vf_id;		/*  vsan tag if applicable	    */ +	__be16	fcxp_tag;	/*  driver request tag		    */ +	__be16	max_frmsz;	/*  max send frame size	    */ +	__be16	vf_id;		/*  vsan tag if applicable	    */  	u16	rport_fw_hndl;	/*  FW Handle for the remote port  */  	u8	 class;		/*  FC class used for req/rsp	    */  	u8	 rsp_timeout;	/*  timeout in secs, 0-no response */  	u8	 cts;		/*  continue sequence		    */ -	u8	 lp_tag;	/*  lport tag			    */ +	u8	 lp_fwtag;	/*  lport tag			    */  	struct fchs_s	fchs;	/*  request FC header structure    */ -	u32	req_len;	/*  request payload length	    */ -	u32	rsp_maxlen;	/*  max response length expected   */ -	struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];	/*  request buf    */ -	struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];	/*  response buf   */ +	__be32	req_len;	/*  request payload length	    */ +	__be32	rsp_maxlen;	/*  max response length expected   */ +	struct bfi_alen_s req_alen;	/* request buffer	*/ +	struct bfi_alen_s rsp_alen;	/* response buffer	*/  };  /* @@ -304,11 +369,11 @@ struct bfi_fcxp_send_req_s {   */  struct bfi_fcxp_send_rsp_s {  	struct bfi_mhdr_s  mh;		/*  Common msg header		    */ -	u16	fcxp_tag;	/*  send request tag		    */ +	__be16	fcxp_tag;	/*  send request tag		    */  	u8	 req_status;	/*  request status		    */  	u8	 rsvd; -	u32	rsp_len;	/*  actual response length	    */ -	u32	residue_len;	/*  residual response length	    */ +	__be32	rsp_len;	/*  actual response length	    */ +	__be32	residue_len;	/*  residual response length	    */  	struct fchs_s	fchs;	/*  response FC header structure   */  }; @@ -325,8 +390,8 @@ enum bfi_uf_i2h {  struct bfi_uf_buf_post_s {  	struct bfi_mhdr_s  mh;		/*  Common msg header		*/  	u16	buf_tag;	/*  buffer tag			*/ -	u16	buf_len;	/*  total buffer length	*/ -	struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs	*/ +	__be16	buf_len;	/*  total buffer length	*/ +	struct bfi_alen_s alen;	/* buffer address/len pair	*/  };  struct bfi_uf_frm_rcvd_s { @@ -340,35 +405,38 @@ struct bfi_uf_frm_rcvd_s {  enum bfi_lps_h2i_msgs {  	BFI_LPS_H2I_LOGIN_REQ	= 1,  	BFI_LPS_H2I_LOGOUT_REQ	= 2, +	BFI_LPS_H2I_N2N_PID_REQ = 3,  };  enum bfi_lps_i2h_msgs { -	BFI_LPS_H2I_LOGIN_RSP	= BFA_I2HM(1), -	BFI_LPS_H2I_LOGOUT_RSP	= BFA_I2HM(2), -	BFI_LPS_H2I_CVL_EVENT	= BFA_I2HM(3), +	BFI_LPS_I2H_LOGIN_RSP	= BFA_I2HM(1), +	BFI_LPS_I2H_LOGOUT_RSP	= BFA_I2HM(2), +	BFI_LPS_I2H_CVL_EVENT	= BFA_I2HM(3),  };  struct bfi_lps_login_req_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		*/ -	u8		lp_tag; +	u8		bfa_tag;  	u8		alpa; -	u16	pdu_size; +	__be16		pdu_size;  	wwn_t		pwwn;  	wwn_t		nwwn;  	u8		fdisc;  	u8		auth_en; -	u8		rsvd[2]; +	u8		lps_role; +	u8		bb_scn; +	u32		vvl_flag;  };  struct bfi_lps_login_rsp_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		*/ -	u8		lp_tag; +	u8		fw_tag;  	u8		status;  	u8		lsrjt_rsn;  	u8		lsrjt_expl;  	wwn_t		port_name;  	wwn_t		node_name; -	u16	bb_credit; +	__be16		bb_credit;  	u8		f_port;  	u8		npiv_en;  	u32	lp_pid:24; @@ -377,32 +445,41 @@ struct bfi_lps_login_rsp_s {  	mac_t		fcf_mac;  	u8		ext_status;  	u8		brcd_switch;	/*  attached peer is brcd switch */ +	u8		bfa_tag; +	u8		rsvd;  };  struct bfi_lps_logout_req_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		*/ -	u8		lp_tag; +	u8		fw_tag;  	u8		rsvd[3];  	wwn_t		port_name;  };  struct bfi_lps_logout_rsp_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		*/ -	u8		lp_tag; +	u8		bfa_tag;  	u8		status;  	u8		rsvd[2];  };  struct bfi_lps_cvl_event_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		*/ -	u8		lp_tag; +	u8		bfa_tag;  	u8		rsvd[3];  }; +struct bfi_lps_n2n_pid_req_s { +	struct bfi_mhdr_s	mh;	/*  common msg header		*/ +	u8	fw_tag; +	u32	lp_pid:24; +}; +  union bfi_lps_h2i_msg_u {  	struct bfi_mhdr_s		*msg;  	struct bfi_lps_login_req_s	*login_req;  	struct bfi_lps_logout_req_s	*logout_req; +	struct bfi_lps_n2n_pid_req_s	*n2n_pid_req;  };  union bfi_lps_i2h_msg_u { @@ -422,14 +499,17 @@ enum bfi_rport_i2h_msgs {  	BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),  	BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),  	BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3), +	BFI_RPORT_I2H_LIP_SCN_ONLINE =	BFA_I2HM(4), +	BFI_RPORT_I2H_LIP_SCN_OFFLINE = BFA_I2HM(5), +	BFI_RPORT_I2H_NO_DEV	= BFA_I2HM(6),  };  struct bfi_rport_create_req_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		*/  	u16	bfa_handle;	/*  host rport handle		*/ -	u16	max_frmsz;	/*  max rcv pdu size		*/ +	__be16	max_frmsz;	/*  max rcv pdu size		*/  	u32	pid:24,	/*  remote port ID		*/ -		lp_tag:8;	/*  local port tag		*/ +		lp_fwtag:8;	/*  local port tag		*/  	u32	local_pid:24,	/*  local port ID		*/  		cisc:8;  	u8	fc_class;	/*  supported FC classes	*/ @@ -474,6 +554,14 @@ struct bfi_rport_qos_scn_s {  	struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */  }; +struct bfi_rport_lip_scn_s { +	struct bfi_mhdr_s  mh;		/*!< common msg header	*/ +	u16	bfa_handle;	/*!< host rport handle	*/ +	u8		status;		/*!< scn online status	*/ +	u8		rsvd; +	struct bfa_fcport_loop_info_s	loop_info; +}; +  union bfi_rport_h2i_msg_u {  	struct bfi_msg_s		*msg;  	struct bfi_rport_create_req_s	*create_req; @@ -486,68 +574,70 @@ union bfi_rport_i2h_msg_u {  	struct bfi_rport_create_rsp_s	*create_rsp;  	struct bfi_rport_delete_rsp_s	*delete_rsp;  	struct bfi_rport_qos_scn_s	*qos_scn_evt; +	struct bfi_rport_lip_scn_s	*lip_scn;  };  /*   * Initiator mode I-T nexus interface defines.   */ -enum bfi_itnim_h2i { -	BFI_ITNIM_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */ -	BFI_ITNIM_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */ +enum bfi_itn_h2i { +	BFI_ITN_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */ +	BFI_ITN_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */  }; -enum bfi_itnim_i2h { -	BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1), -	BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2), -	BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3), +enum bfi_itn_i2h { +	BFI_ITN_I2H_CREATE_RSP = BFA_I2HM(1), +	BFI_ITN_I2H_DELETE_RSP = BFA_I2HM(2), +	BFI_ITN_I2H_SLER_EVENT = BFA_I2HM(3),  }; -struct bfi_itnim_create_req_s { +struct bfi_itn_create_req_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		 */  	u16	fw_handle;	/*  f/w handle for itnim	 */  	u8	class;		/*  FC class for IO		 */  	u8	seq_rec;	/*  sequence recovery support	 */  	u8	msg_no;		/*  seq id of the msg		 */ +	u8	role;  }; -struct bfi_itnim_create_rsp_s { +struct bfi_itn_create_rsp_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		 */  	u16	bfa_handle;	/*  bfa handle for itnim	 */  	u8	status;		/*  fcp request status		 */  	u8	seq_id;		/*  seq id of the msg		 */  }; -struct bfi_itnim_delete_req_s { +struct bfi_itn_delete_req_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		 */  	u16	fw_handle;	/*  f/w itnim handle		 */  	u8	seq_id;		/*  seq id of the msg		 */  	u8	rsvd;  }; -struct bfi_itnim_delete_rsp_s { +struct bfi_itn_delete_rsp_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		 */  	u16	bfa_handle;	/*  bfa handle for itnim	 */  	u8	status;		/*  fcp request status		 */  	u8	seq_id;		/*  seq id of the msg		 */  }; -struct bfi_itnim_sler_event_s { +struct bfi_itn_sler_event_s {  	struct bfi_mhdr_s  mh;		/*  common msg header		 */  	u16	bfa_handle;	/*  bfa handle for itnim	 */  	u16	rsvd;  }; -union bfi_itnim_h2i_msg_u { -	struct bfi_itnim_create_req_s *create_req; -	struct bfi_itnim_delete_req_s *delete_req; +union bfi_itn_h2i_msg_u { +	struct bfi_itn_create_req_s *create_req; +	struct bfi_itn_delete_req_s *delete_req;  	struct bfi_msg_s	*msg;  }; -union bfi_itnim_i2h_msg_u { -	struct bfi_itnim_create_rsp_s *create_rsp; -	struct bfi_itnim_delete_rsp_s *delete_rsp; -	struct bfi_itnim_sler_event_s *sler_event; +union bfi_itn_i2h_msg_u { +	struct bfi_itn_create_rsp_s *create_rsp; +	struct bfi_itn_delete_rsp_s *delete_rsp; +	struct bfi_itn_sler_event_s *sler_event;  	struct bfi_msg_s	*msg;  }; @@ -583,7 +673,7 @@ struct bfi_ioim_dif_s {   */  struct bfi_ioim_req_s {  	struct bfi_mhdr_s  mh;		/*  Common msg header		 */ -	u16	io_tag;		/*  I/O tag			 */ +	__be16	io_tag;		/*  I/O tag			 */  	u16	rport_hdl;	/*  itnim/rport firmware handle */  	struct fcp_cmnd_s	cmnd;	/*  IO request info	*/ @@ -683,13 +773,12 @@ enum bfi_ioim_status {  	BFI_IOIM_STS_PATHTOV = 8,  }; -#define BFI_IOIM_SNSLEN	(256)  /*   * I/O response message   */  struct bfi_ioim_rsp_s {  	struct bfi_mhdr_s	mh;	/*  common msg header		*/ -	u16	io_tag;		/*  completed IO tag		 */ +	__be16	io_tag;		/*  completed IO tag		 */  	u16	bfa_rport_hndl;	/*  releated rport handle	 */  	u8	io_status;	/*  IO completion status	 */  	u8	reuse_io_tag;	/*  IO tag can be reused	*/ @@ -698,13 +787,13 @@ struct bfi_ioim_rsp_s {  	u8		sns_len;	/*  scsi sense length		 */  	u8		resid_flags;	/*  IO residue flags		 */  	u8		rsvd_a; -	u32	residue;	/*  IO residual length in bytes */ +	__be32	residue;	/*  IO residual length in bytes */  	u32	rsvd_b[3];  };  struct bfi_ioim_abort_req_s {  	struct bfi_mhdr_s  mh;	/*  Common msg header  */ -	u16	io_tag;	/*  I/O tag	*/ +	__be16	io_tag;	/*  I/O tag	*/  	u16	abort_tag;	/*  unique request tag */  }; @@ -723,9 +812,9 @@ enum bfi_tskim_i2h {  struct bfi_tskim_req_s {  	struct bfi_mhdr_s  mh;	/*  Common msg header	*/ -	u16	tsk_tag;	/*  task management tag	*/ +	__be16	tsk_tag;	/*  task management tag	*/  	u16	itn_fhdl;	/*  itn firmware handle	*/ -	lun_t	lun;	/*  LU number	*/ +	struct 	scsi_lun lun;	/*  LU number	*/  	u8	tm_flags;	/*  see enum fcp_tm_cmnd	*/  	u8	t_secs;	/*  Timeout value in seconds	*/  	u8	rsvd[2]; @@ -733,7 +822,7 @@ struct bfi_tskim_req_s {  struct bfi_tskim_abortreq_s {  	struct bfi_mhdr_s  mh;	/*  Common msg header	*/ -	u16	tsk_tag;	/*  task management tag	*/ +	__be16	tsk_tag;	/*  task management tag	*/  	u16	rsvd;  }; @@ -751,15 +840,39 @@ enum bfi_tskim_status {  	 */  	BFI_TSKIM_STS_TIMEOUT  = 10,	/*  TM request timedout	*/  	BFI_TSKIM_STS_ABORTED  = 11,	/*  Aborted on host request */ +	BFI_TSKIM_STS_UTAG     = 12,	/*  unknown tag for request */  };  struct bfi_tskim_rsp_s {  	struct bfi_mhdr_s  mh;		/*  Common msg header		 */ -	u16	tsk_tag;	/*  task mgmt cmnd tag		 */ +	__be16	tsk_tag;	/*  task mgmt cmnd tag		 */  	u8	tsk_status;	/*  @ref bfi_tskim_status */  	u8	rsvd;  };  #pragma pack() +/* + * Crossbow PCI MSI-X vector defines + */ +enum { +	BFI_MSIX_CPE_QMIN_CB = 0, +	BFI_MSIX_CPE_QMAX_CB = 7, +	BFI_MSIX_RME_QMIN_CB = 8, +	BFI_MSIX_RME_QMAX_CB = 15, +	BFI_MSIX_CB_MAX = 22, +}; + +/* + * Catapult FC PCI MSI-X vector defines + */ +enum { +	BFI_MSIX_LPU_ERR_CT = 0, +	BFI_MSIX_CPE_QMIN_CT = 1, +	BFI_MSIX_CPE_QMAX_CT = 4, +	BFI_MSIX_RME_QMIN_CT = 5, +	BFI_MSIX_RME_QMAX_CT = 8, +	BFI_MSIX_CT_MAX = 9, +}; +  #endif /* __BFI_MS_H__ */ diff --git a/drivers/scsi/bfa/bfi_reg.h b/drivers/scsi/bfa/bfi_reg.h new file mode 100644 index 00000000000..99133bcf53f --- /dev/null +++ b/drivers/scsi/bfa/bfi_reg.h @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. + * All rights reserved + * www.brocade.com + * + * Linux driver for Brocade Fibre Channel Host Bus Adapter. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (GPL) Version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +/* + * bfi_reg.h ASIC register defines for all Brocade adapter ASICs + */ + +#ifndef __BFI_REG_H__ +#define __BFI_REG_H__ + +#define HOSTFN0_INT_STATUS		0x00014000	/* cb/ct	*/ +#define HOSTFN1_INT_STATUS		0x00014100	/* cb/ct	*/ +#define HOSTFN2_INT_STATUS		0x00014300	/* ct		*/ +#define HOSTFN3_INT_STATUS		0x00014400	/* ct		*/ +#define HOSTFN0_INT_MSK			0x00014004	/* cb/ct	*/ +#define HOSTFN1_INT_MSK			0x00014104	/* cb/ct	*/ +#define HOSTFN2_INT_MSK			0x00014304	/* ct		*/ +#define HOSTFN3_INT_MSK			0x00014404	/* ct		*/ + +#define HOST_PAGE_NUM_FN0		0x00014008	/* cb/ct	*/ +#define HOST_PAGE_NUM_FN1		0x00014108	/* cb/ct	*/ +#define HOST_PAGE_NUM_FN2		0x00014308	/* ct		*/ +#define HOST_PAGE_NUM_FN3		0x00014408	/* ct		*/ + +#define APP_PLL_LCLK_CTL_REG		0x00014204	/* cb/ct	*/ +#define __P_LCLK_PLL_LOCK		0x80000000 +#define __APP_PLL_LCLK_SRAM_USE_100MHZ	0x00100000 +#define __APP_PLL_LCLK_RESET_TIMER_MK	0x000e0000 +#define __APP_PLL_LCLK_RESET_TIMER_SH	17 +#define __APP_PLL_LCLK_RESET_TIMER(_v)	((_v) << __APP_PLL_LCLK_RESET_TIMER_SH) +#define __APP_PLL_LCLK_LOGIC_SOFT_RESET	0x00010000 +#define __APP_PLL_LCLK_CNTLMT0_1_MK	0x0000c000 +#define __APP_PLL_LCLK_CNTLMT0_1_SH	14 +#define __APP_PLL_LCLK_CNTLMT0_1(_v)	((_v) << __APP_PLL_LCLK_CNTLMT0_1_SH) +#define __APP_PLL_LCLK_JITLMT0_1_MK	0x00003000 +#define __APP_PLL_LCLK_JITLMT0_1_SH	12 +#define __APP_PLL_LCLK_JITLMT0_1(_v)	((_v) << __APP_PLL_LCLK_JITLMT0_1_SH) +#define __APP_PLL_LCLK_HREF		0x00000800 +#define __APP_PLL_LCLK_HDIV		0x00000400 +#define __APP_PLL_LCLK_P0_1_MK		0x00000300 +#define __APP_PLL_LCLK_P0_1_SH		8 +#define __APP_PLL_LCLK_P0_1(_v)		((_v) << __APP_PLL_LCLK_P0_1_SH) +#define __APP_PLL_LCLK_Z0_2_MK		0x000000e0 +#define __APP_PLL_LCLK_Z0_2_SH		5 +#define __APP_PLL_LCLK_Z0_2(_v)		((_v) << __APP_PLL_LCLK_Z0_2_SH) +#define __APP_PLL_LCLK_RSEL200500	0x00000010 +#define __APP_PLL_LCLK_ENARST		0x00000008 +#define __APP_PLL_LCLK_BYPASS		0x00000004 +#define __APP_PLL_LCLK_LRESETN		0x00000002 +#define __APP_PLL_LCLK_ENABLE		0x00000001 +#define APP_PLL_SCLK_CTL_REG		0x00014208	/* cb/ct	*/ +#define __P_SCLK_PLL_LOCK		0x80000000 +#define __APP_PLL_SCLK_RESET_TIMER_MK	0x000e0000 +#define __APP_PLL_SCLK_RESET_TIMER_SH	17 +#define __APP_PLL_SCLK_RESET_TIMER(_v)	((_v) << __APP_PLL_SCLK_RESET_TIMER_SH) +#define __APP_PLL_SCLK_LOGIC_SOFT_RESET	0x00010000 +#define __APP_PLL_SCLK_CNTLMT0_1_MK	0x0000c000 +#define __APP_PLL_SCLK_CNTLMT0_1_SH	14 +#define __APP_PLL_SCLK_CNTLMT0_1(_v)	((_v) << __APP_PLL_SCLK_CNTLMT0_1_SH) +#define __APP_PLL_SCLK_JITLMT0_1_MK	0x00003000 +#define __APP_PLL_SCLK_JITLMT0_1_SH	12 +#define __APP_PLL_SCLK_JITLMT0_1(_v)	((_v) << __APP_PLL_SCLK_JITLMT0_1_SH) +#define __APP_PLL_SCLK_HREF		0x00000800 +#define __APP_PLL_SCLK_HDIV		0x00000400 +#define __APP_PLL_SCLK_P0_1_MK		0x00000300 +#define __APP_PLL_SCLK_P0_1_SH		8 +#define __APP_PLL_SCLK_P0_1(_v)		((_v) << __APP_PLL_SCLK_P0_1_SH) +#define __APP_PLL_SCLK_Z0_2_MK		0x000000e0 +#define __APP_PLL_SCLK_Z0_2_SH		5 +#define __APP_PLL_SCLK_Z0_2(_v)		((_v) << __APP_PLL_SCLK_Z0_2_SH) +#define __APP_PLL_SCLK_RSEL200500	0x00000010 +#define __APP_PLL_SCLK_ENARST		0x00000008 +#define __APP_PLL_SCLK_BYPASS		0x00000004 +#define __APP_PLL_SCLK_LRESETN		0x00000002 +#define __APP_PLL_SCLK_ENABLE		0x00000001 +#define __ENABLE_MAC_AHB_1		0x00800000	/* ct		*/ +#define __ENABLE_MAC_AHB_0		0x00400000	/* ct		*/ +#define __ENABLE_MAC_1			0x00200000	/* ct		*/ +#define __ENABLE_MAC_0			0x00100000	/* ct		*/ + +#define HOST_SEM0_REG			0x00014230	/* cb/ct	*/ +#define HOST_SEM1_REG			0x00014234	/* cb/ct	*/ +#define HOST_SEM2_REG			0x00014238	/* cb/ct	*/ +#define HOST_SEM3_REG			0x0001423c	/* cb/ct	*/ +#define HOST_SEM4_REG			0x00014610	/* cb/ct	*/ +#define HOST_SEM5_REG			0x00014614	/* cb/ct	*/ +#define HOST_SEM6_REG			0x00014618	/* cb/ct	*/ +#define HOST_SEM7_REG			0x0001461c	/* cb/ct	*/ +#define HOST_SEM0_INFO_REG		0x00014240	/* cb/ct	*/ +#define HOST_SEM1_INFO_REG		0x00014244	/* cb/ct	*/ +#define HOST_SEM2_INFO_REG		0x00014248	/* cb/ct	*/ +#define HOST_SEM3_INFO_REG		0x0001424c	/* cb/ct	*/ +#define HOST_SEM4_INFO_REG		0x00014620	/* cb/ct	*/ +#define HOST_SEM5_INFO_REG		0x00014624	/* cb/ct	*/ +#define HOST_SEM6_INFO_REG		0x00014628	/* cb/ct	*/ +#define HOST_SEM7_INFO_REG		0x0001462c	/* cb/ct	*/ + +#define HOSTFN0_LPU0_CMD_STAT		0x00019000	/* cb/ct	*/ +#define HOSTFN0_LPU1_CMD_STAT		0x00019004	/* cb/ct	*/ +#define HOSTFN1_LPU0_CMD_STAT		0x00019010	/* cb/ct	*/ +#define HOSTFN1_LPU1_CMD_STAT		0x00019014	/* cb/ct	*/ +#define HOSTFN2_LPU0_CMD_STAT		0x00019150	/* ct		*/ +#define HOSTFN2_LPU1_CMD_STAT		0x00019154	/* ct		*/ +#define HOSTFN3_LPU0_CMD_STAT		0x00019160	/* ct		*/ +#define HOSTFN3_LPU1_CMD_STAT		0x00019164	/* ct		*/ +#define LPU0_HOSTFN0_CMD_STAT		0x00019008	/* cb/ct	*/ +#define LPU1_HOSTFN0_CMD_STAT		0x0001900c	/* cb/ct	*/ +#define LPU0_HOSTFN1_CMD_STAT		0x00019018	/* cb/ct	*/ +#define LPU1_HOSTFN1_CMD_STAT		0x0001901c	/* cb/ct	*/ +#define LPU0_HOSTFN2_CMD_STAT		0x00019158	/* ct		*/ +#define LPU1_HOSTFN2_CMD_STAT		0x0001915c	/* ct		*/ +#define LPU0_HOSTFN3_CMD_STAT		0x00019168	/* ct		*/ +#define LPU1_HOSTFN3_CMD_STAT		0x0001916c	/* ct		*/ + +#define PSS_CTL_REG			0x00018800	/* cb/ct	*/ +#define __PSS_I2C_CLK_DIV_MK		0x007f0000 +#define __PSS_I2C_CLK_DIV_SH		16 +#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH) +#define __PSS_LMEM_INIT_DONE		0x00001000 +#define __PSS_LMEM_RESET		0x00000200 +#define __PSS_LMEM_INIT_EN		0x00000100 +#define __PSS_LPU1_RESET		0x00000002 +#define __PSS_LPU0_RESET		0x00000001 +#define PSS_ERR_STATUS_REG		0x00018810	/* cb/ct	*/ +#define ERR_SET_REG			0x00018818	/* cb/ct	*/ +#define PSS_GPIO_OUT_REG		0x000188c0	/* cb/ct	*/ +#define __PSS_GPIO_OUT_REG		0x00000fff +#define PSS_GPIO_OE_REG			0x000188c8	/* cb/ct	*/ +#define __PSS_GPIO_OE_REG		0x000000ff + +#define HOSTFN0_LPU_MBOX0_0		0x00019200	/* cb/ct	*/ +#define HOSTFN1_LPU_MBOX0_8		0x00019260	/* cb/ct	*/ +#define LPU_HOSTFN0_MBOX0_0		0x00019280	/* cb/ct	*/ +#define LPU_HOSTFN1_MBOX0_8		0x000192e0	/* cb/ct	*/ +#define HOSTFN2_LPU_MBOX0_0		0x00019400	/* ct		*/ +#define HOSTFN3_LPU_MBOX0_8		0x00019460	/* ct		*/ +#define LPU_HOSTFN2_MBOX0_0		0x00019480	/* ct		*/ +#define LPU_HOSTFN3_MBOX0_8		0x000194e0	/* ct		*/ + +#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c	/* ct		*/ +#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c	/* ct		*/ +#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c	/* ct		*/ +#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c	/* ct		*/ + +#define MBIST_CTL_REG			0x00014220	/* ct		*/ +#define __EDRAM_BISTR_START		0x00000004 +#define MBIST_STAT_REG			0x00014224	/* ct		*/ +#define ETH_MAC_SER_REG			0x00014288	/* ct		*/ +#define __APP_EMS_CKBUFAMPIN		0x00000020 +#define __APP_EMS_REFCLKSEL		0x00000010 +#define __APP_EMS_CMLCKSEL		0x00000008 +#define __APP_EMS_REFCKBUFEN2		0x00000004 +#define __APP_EMS_REFCKBUFEN1		0x00000002 +#define __APP_EMS_CHANNEL_SEL		0x00000001 +#define FNC_PERS_REG			0x00014604	/* ct		*/ +#define __F3_FUNCTION_ACTIVE		0x80000000 +#define __F3_FUNCTION_MODE		0x40000000 +#define __F3_PORT_MAP_MK		0x30000000 +#define __F3_PORT_MAP_SH		28 +#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH) +#define __F3_VM_MODE			0x08000000 +#define __F3_INTX_STATUS_MK		0x07000000 +#define __F3_INTX_STATUS_SH		24 +#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH) +#define __F2_FUNCTION_ACTIVE		0x00800000 +#define __F2_FUNCTION_MODE		0x00400000 +#define __F2_PORT_MAP_MK		0x00300000 +#define __F2_PORT_MAP_SH		20 +#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH) +#define __F2_VM_MODE			0x00080000 +#define __F2_INTX_STATUS_MK		0x00070000 +#define __F2_INTX_STATUS_SH		16 +#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH) +#define __F1_FUNCTION_ACTIVE		0x00008000 +#define __F1_FUNCTION_MODE		0x00004000 +#define __F1_PORT_MAP_MK		0x00003000 +#define __F1_PORT_MAP_SH		12 +#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH) +#define __F1_VM_MODE			0x00000800 +#define __F1_INTX_STATUS_MK		0x00000700 +#define __F1_INTX_STATUS_SH		8 +#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH) +#define __F0_FUNCTION_ACTIVE		0x00000080 +#define __F0_FUNCTION_MODE		0x00000040 +#define __F0_PORT_MAP_MK		0x00000030 +#define __F0_PORT_MAP_SH		4 +#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH) +#define __F0_VM_MODE			0x00000008 +#define __F0_INTX_STATUS		0x00000007 +enum { +	__F0_INTX_STATUS_MSIX = 0x0, +	__F0_INTX_STATUS_INTA = 0x1, +	__F0_INTX_STATUS_INTB = 0x2, +	__F0_INTX_STATUS_INTC = 0x3, +	__F0_INTX_STATUS_INTD = 0x4, +}; + +#define OP_MODE				0x0001460c	/* ct		*/ +#define __APP_ETH_CLK_LOWSPEED		0x00000004 +#define __GLOBAL_CORECLK_HALFSPEED	0x00000002 +#define __GLOBAL_FCOE_MODE		0x00000001 +#define FW_INIT_HALT_P0			0x000191ac	/* ct		*/ +#define __FW_INIT_HALT_P		0x00000001 +#define FW_INIT_HALT_P1			0x000191bc	/* ct		*/ +#define PMM_1T_RESET_REG_P0		0x0002381c	/* ct		*/ +#define __PMM_1T_RESET_P		0x00000001 +#define PMM_1T_RESET_REG_P1		0x00023c1c	/* ct		*/ + +/** + * Catapult-2 specific defines + */ +#define CT2_PCI_CPQ_BASE		0x00030000 +#define CT2_PCI_APP_BASE		0x00030100 +#define CT2_PCI_ETH_BASE		0x00030400 + +/* + * APP block registers + */ +#define CT2_HOSTFN_INT_STATUS		(CT2_PCI_APP_BASE + 0x00) +#define CT2_HOSTFN_INTR_MASK		(CT2_PCI_APP_BASE + 0x04) +#define CT2_HOSTFN_PERSONALITY0		(CT2_PCI_APP_BASE + 0x08) +#define __PME_STATUS_			0x00200000 +#define __PF_VF_BAR_SIZE_MODE__MK	0x00180000 +#define __PF_VF_BAR_SIZE_MODE__SH	19 +#define __PF_VF_BAR_SIZE_MODE_(_v)	((_v) << __PF_VF_BAR_SIZE_MODE__SH) +#define __FC_LL_PORT_MAP__MK		0x00060000 +#define __FC_LL_PORT_MAP__SH		17 +#define __FC_LL_PORT_MAP_(_v)		((_v) << __FC_LL_PORT_MAP__SH) +#define __PF_VF_ACTIVE_			0x00010000 +#define __PF_VF_CFG_RDY_		0x00008000 +#define __PF_VF_ENABLE_			0x00004000 +#define __PF_DRIVER_ACTIVE_		0x00002000 +#define __PF_PME_SEND_ENABLE_		0x00001000 +#define __PF_EXROM_OFFSET__MK		0x00000ff0 +#define __PF_EXROM_OFFSET__SH		4 +#define __PF_EXROM_OFFSET_(_v)		((_v) << __PF_EXROM_OFFSET__SH) +#define __FC_LL_MODE_			0x00000008 +#define __PF_INTX_PIN_			0x00000007 +#define CT2_HOSTFN_PERSONALITY1		(CT2_PCI_APP_BASE + 0x0C) +#define __PF_NUM_QUEUES1__MK		0xff000000 +#define __PF_NUM_QUEUES1__SH		24 +#define __PF_NUM_QUEUES1_(_v)		((_v) << __PF_NUM_QUEUES1__SH) +#define __PF_VF_QUE_OFFSET1__MK		0x00ff0000 +#define __PF_VF_QUE_OFFSET1__SH		16 +#define __PF_VF_QUE_OFFSET1_(_v)	((_v) << __PF_VF_QUE_OFFSET1__SH) +#define __PF_VF_NUM_QUEUES__MK		0x0000ff00 +#define __PF_VF_NUM_QUEUES__SH		8 +#define __PF_VF_NUM_QUEUES_(_v)		((_v) << __PF_VF_NUM_QUEUES__SH) +#define __PF_VF_QUE_OFFSET_		0x000000ff +#define CT2_HOSTFN_PAGE_NUM		(CT2_PCI_APP_BASE + 0x18) +#define CT2_HOSTFN_MSIX_VT_INDEX_MBOX_ERR	(CT2_PCI_APP_BASE + 0x38) + +/* + * Catapult-2 CPQ block registers + */ +#define CT2_HOSTFN_LPU0_MBOX0		(CT2_PCI_CPQ_BASE + 0x00) +#define CT2_HOSTFN_LPU1_MBOX0		(CT2_PCI_CPQ_BASE + 0x20) +#define CT2_LPU0_HOSTFN_MBOX0		(CT2_PCI_CPQ_BASE + 0x40) +#define CT2_LPU1_HOSTFN_MBOX0		(CT2_PCI_CPQ_BASE + 0x60) +#define CT2_HOSTFN_LPU0_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x80) +#define CT2_HOSTFN_LPU1_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x84) +#define CT2_LPU0_HOSTFN_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x88) +#define CT2_LPU1_HOSTFN_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x8c) +#define CT2_HOSTFN_LPU0_READ_STAT	(CT2_PCI_CPQ_BASE + 0x90) +#define CT2_HOSTFN_LPU1_READ_STAT	(CT2_PCI_CPQ_BASE + 0x94) +#define CT2_LPU0_HOSTFN_MBOX0_MSK	(CT2_PCI_CPQ_BASE + 0x98) +#define CT2_LPU1_HOSTFN_MBOX0_MSK	(CT2_PCI_CPQ_BASE + 0x9C) +#define CT2_HOST_SEM0_REG		0x000148f0 +#define CT2_HOST_SEM1_REG		0x000148f4 +#define CT2_HOST_SEM2_REG		0x000148f8 +#define CT2_HOST_SEM3_REG		0x000148fc +#define CT2_HOST_SEM4_REG		0x00014900 +#define CT2_HOST_SEM5_REG		0x00014904 +#define CT2_HOST_SEM6_REG		0x00014908 +#define CT2_HOST_SEM7_REG		0x0001490c +#define CT2_HOST_SEM0_INFO_REG		0x000148b0 +#define CT2_HOST_SEM1_INFO_REG		0x000148b4 +#define CT2_HOST_SEM2_INFO_REG		0x000148b8 +#define CT2_HOST_SEM3_INFO_REG		0x000148bc +#define CT2_HOST_SEM4_INFO_REG		0x000148c0 +#define CT2_HOST_SEM5_INFO_REG		0x000148c4 +#define CT2_HOST_SEM6_INFO_REG		0x000148c8 +#define CT2_HOST_SEM7_INFO_REG		0x000148cc + +#define CT2_APP_PLL_LCLK_CTL_REG	0x00014808 +#define __APP_LPUCLK_HALFSPEED		0x40000000 +#define __APP_PLL_LCLK_LOAD		0x20000000 +#define __APP_PLL_LCLK_FBCNT_MK		0x1fe00000 +#define __APP_PLL_LCLK_FBCNT_SH		21 +#define __APP_PLL_LCLK_FBCNT(_v)	((_v) << __APP_PLL_SCLK_FBCNT_SH) +enum { +	__APP_PLL_LCLK_FBCNT_425_MHZ = 6, +	__APP_PLL_LCLK_FBCNT_468_MHZ = 4, +}; +#define __APP_PLL_LCLK_EXTFB		0x00000800 +#define __APP_PLL_LCLK_ENOUTS		0x00000400 +#define __APP_PLL_LCLK_RATE		0x00000010 +#define CT2_APP_PLL_SCLK_CTL_REG	0x0001480c +#define __P_SCLK_PLL_LOCK		0x80000000 +#define __APP_PLL_SCLK_REFCLK_SEL	0x40000000 +#define __APP_PLL_SCLK_CLK_DIV2		0x20000000 +#define __APP_PLL_SCLK_LOAD		0x10000000 +#define __APP_PLL_SCLK_FBCNT_MK		0x0ff00000 +#define __APP_PLL_SCLK_FBCNT_SH		20 +#define __APP_PLL_SCLK_FBCNT(_v)	((_v) << __APP_PLL_SCLK_FBCNT_SH) +enum { +	__APP_PLL_SCLK_FBCNT_NORM = 6, +	__APP_PLL_SCLK_FBCNT_10G_FC = 10, +}; +#define __APP_PLL_SCLK_EXTFB		0x00000800 +#define __APP_PLL_SCLK_ENOUTS		0x00000400 +#define __APP_PLL_SCLK_RATE		0x00000010 +#define CT2_PCIE_MISC_REG		0x00014804 +#define __ETH_CLK_ENABLE_PORT1		0x00000010 +#define CT2_CHIP_MISC_PRG		0x000148a4 +#define __ETH_CLK_ENABLE_PORT0		0x00004000 +#define __APP_LPU_SPEED			0x00000002 +#define CT2_MBIST_STAT_REG		0x00014818 +#define CT2_MBIST_CTL_REG		0x0001481c +#define CT2_PMM_1T_CONTROL_REG_P0	0x0002381c +#define __PMM_1T_PNDB_P			0x00000002 +#define CT2_PMM_1T_CONTROL_REG_P1	0x00023c1c +#define CT2_WGN_STATUS			0x00014990 +#define __A2T_AHB_LOAD			0x00000800 +#define __WGN_READY			0x00000400 +#define __GLBL_PF_VF_CFG_RDY		0x00000200 +#define CT2_NFC_STS_REG			0x00027410 +#define CT2_NFC_CSR_CLR_REG		0x00027420 +#define CT2_NFC_CSR_SET_REG		0x00027424 +#define __HALT_NFC_CONTROLLER		0x00000002 +#define __NFC_CONTROLLER_HALTED		0x00001000 +#define CT2_RSC_GPR15_REG		0x0002765c +#define CT2_CSI_FW_CTL_REG		0x00027080 +#define CT2_CSI_FW_CTL_SET_REG		0x00027088 +#define __RESET_AND_START_SCLK_LCLK_PLLS 0x00010000 + +#define CT2_CSI_MAC0_CONTROL_REG	0x000270d0 +#define __CSI_MAC_RESET			0x00000010 +#define __CSI_MAC_AHB_RESET		0x00000008 +#define CT2_CSI_MAC1_CONTROL_REG	0x000270d4 +#define CT2_CSI_MAC_CONTROL_REG(__n)	\ +	(CT2_CSI_MAC0_CONTROL_REG +	\ +	(__n) * (CT2_CSI_MAC1_CONTROL_REG - CT2_CSI_MAC0_CONTROL_REG)) + +#define CT2_NFC_FLASH_STS_REG		0x00014834 +#define __FLASH_PLL_INIT_AND_RESET_IN_PROGRESS	0x00000020 +/* + * Name semaphore registers based on usage + */ +#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG +#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG +#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG +#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG +#define BFA_FW_USE_COUNT		HOST_SEM4_INFO_REG +#define BFA_IOC_FAIL_SYNC		HOST_SEM5_INFO_REG + +/* + * CT2 semaphore register locations changed + */ +#define CT2_BFA_IOC0_HBEAT_REG		CT2_HOST_SEM0_INFO_REG +#define CT2_BFA_IOC0_STATE_REG		CT2_HOST_SEM1_INFO_REG +#define CT2_BFA_IOC1_HBEAT_REG		CT2_HOST_SEM2_INFO_REG +#define CT2_BFA_IOC1_STATE_REG		CT2_HOST_SEM3_INFO_REG +#define CT2_BFA_FW_USE_COUNT		CT2_HOST_SEM4_INFO_REG +#define CT2_BFA_IOC_FAIL_SYNC		CT2_HOST_SEM5_INFO_REG + +#define CPE_Q_NUM(__fn, __q)	(((__fn) << 2) + (__q)) +#define RME_Q_NUM(__fn, __q)	(((__fn) << 2) + (__q)) + +/* + * And corresponding host interrupt status bit field defines + */ +#define __HFN_INT_CPE_Q0	0x00000001U +#define __HFN_INT_CPE_Q1	0x00000002U +#define __HFN_INT_CPE_Q2	0x00000004U +#define __HFN_INT_CPE_Q3	0x00000008U +#define __HFN_INT_CPE_Q4	0x00000010U +#define __HFN_INT_CPE_Q5	0x00000020U +#define __HFN_INT_CPE_Q6	0x00000040U +#define __HFN_INT_CPE_Q7	0x00000080U +#define __HFN_INT_RME_Q0	0x00000100U +#define __HFN_INT_RME_Q1	0x00000200U +#define __HFN_INT_RME_Q2	0x00000400U +#define __HFN_INT_RME_Q3	0x00000800U +#define __HFN_INT_RME_Q4	0x00001000U +#define __HFN_INT_RME_Q5	0x00002000U +#define __HFN_INT_RME_Q6	0x00004000U +#define __HFN_INT_RME_Q7	0x00008000U +#define __HFN_INT_ERR_EMC	0x00010000U +#define __HFN_INT_ERR_LPU0	0x00020000U +#define __HFN_INT_ERR_LPU1	0x00040000U +#define __HFN_INT_ERR_PSS	0x00080000U +#define __HFN_INT_MBOX_LPU0	0x00100000U +#define __HFN_INT_MBOX_LPU1	0x00200000U +#define __HFN_INT_MBOX1_LPU0	0x00400000U +#define __HFN_INT_MBOX1_LPU1	0x00800000U +#define __HFN_INT_LL_HALT	0x01000000U +#define __HFN_INT_CPE_MASK	0x000000ffU +#define __HFN_INT_RME_MASK	0x0000ff00U +#define __HFN_INT_ERR_MASK	\ +	(__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | \ +	 __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT) +#define __HFN_INT_FN0_MASK	\ +	(__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \ +	 __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \ +	 __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0) +#define __HFN_INT_FN1_MASK	\ +	(__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \ +	 __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \ +	 __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1) + +/* + * Host interrupt status defines for catapult-2 + */ +#define __HFN_INT_MBOX_LPU0_CT2	0x00010000U +#define __HFN_INT_MBOX_LPU1_CT2	0x00020000U +#define __HFN_INT_ERR_PSS_CT2	0x00040000U +#define __HFN_INT_ERR_LPU0_CT2	0x00080000U +#define __HFN_INT_ERR_LPU1_CT2	0x00100000U +#define __HFN_INT_CPQ_HALT_CT2	0x00200000U +#define __HFN_INT_ERR_WGN_CT2	0x00400000U +#define __HFN_INT_ERR_LEHRX_CT2	0x00800000U +#define __HFN_INT_ERR_LEHTX_CT2	0x01000000U +#define __HFN_INT_ERR_MASK_CT2	\ +	(__HFN_INT_ERR_PSS_CT2 | __HFN_INT_ERR_LPU0_CT2 | \ +	 __HFN_INT_ERR_LPU1_CT2 | __HFN_INT_CPQ_HALT_CT2 | \ +	 __HFN_INT_ERR_WGN_CT2 | __HFN_INT_ERR_LEHRX_CT2 | \ +	 __HFN_INT_ERR_LEHTX_CT2) +#define __HFN_INT_FN0_MASK_CT2	\ +	(__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \ +	 __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \ +	 __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0_CT2) +#define __HFN_INT_FN1_MASK_CT2	\ +	(__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \ +	 __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \ +	 __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1_CT2) + +/* + * asic memory map. + */ +#define PSS_SMEM_PAGE_START		0x8000 +#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15)) +#define PSS_SMEM_PGOFF(_ma)		((_ma) & 0x7fff) + +#endif /* __BFI_REG_H__ */  | 
