Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,6 @@
obj-$(CONFIG_SCSI_BFA_FC) := bfa.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_svc.o

448
drivers/scsi/bfa/bfa.h Normal file
View file

@ -0,0 +1,448 @@
/*
* 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_H__
#define __BFA_H__
#include "bfad_drv.h"
#include "bfa_cs.h"
#include "bfa_plog.h"
#include "bfa_defs_svc.h"
#include "bfi.h"
#include "bfa_ioc.h"
struct bfa_s;
typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
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);
/*
* Request and response queue related defines
*/
#define BFA_REQQ_NELEMS_MIN (4)
#define BFA_RSPQ_NELEMS_MIN (4)
#define bfa_reqq_pi(__bfa, __reqq) ((__bfa)->iocfc.req_cq_pi[__reqq])
#define bfa_reqq_ci(__bfa, __reqq) \
(*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
#define bfa_reqq_full(__bfa, __reqq) \
(((bfa_reqq_pi(__bfa, __reqq) + 1) & \
((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) == \
bfa_reqq_ci(__bfa, __reqq))
#define bfa_reqq_next(__bfa, __reqq) \
(bfa_reqq_full(__bfa, __reqq) ? NULL : \
((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
+ bfa_reqq_pi((__bfa), (__reqq)))))
#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); \
writel((__bfa)->iocfc.req_cq_pi[__reqq], \
(__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq]); \
mmiowb(); \
} while (0)
#define bfa_rspq_pi(__bfa, __rspq) \
(*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
#define bfa_rspq_ci(__bfa, __rspq) ((__bfa)->iocfc.rsp_cq_ci[__rspq])
#define bfa_rspq_elem(__bfa, __rspq, __ci) \
(&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
#define CQ_INCR(__index, __size) do { \
(__index)++; \
(__index) &= ((__size) - 1); \
} while (0)
/*
* Circular queue usage assignments
*/
enum {
BFA_REQQ_IOC = 0, /* all low-priority IOC msgs */
BFA_REQQ_FCXP = 0, /* all FCXP messages */
BFA_REQQ_LPS = 0, /* all lport service msgs */
BFA_REQQ_PORT = 0, /* all port messages */
BFA_REQQ_FLASH = 0, /* for flash module */
BFA_REQQ_DIAG = 0, /* for diag module */
BFA_REQQ_RPORT = 0, /* all port messages */
BFA_REQQ_SBOOT = 0, /* all san boot messages */
BFA_REQQ_QOS_LO = 1, /* all low priority IO */
BFA_REQQ_QOS_MD = 2, /* all medium priority IO */
BFA_REQQ_QOS_HI = 3, /* all high priority IO */
};
static inline void
bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
void *cbarg)
{
wqe->qresume = qresume;
wqe->cbarg = cbarg;
}
#define bfa_reqq(__bfa, __reqq) (&(__bfa)->reqq_waitq[__reqq])
/*
* static inline void
* bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
*/
#define bfa_reqq_wait(__bfa, __reqq, __wqe) do { \
\
struct list_head *waitq = bfa_reqq(__bfa, __reqq); \
\
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)
#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)
#define bfa_cb_dequeue(__hcb_qe) list_del(&(__hcb_qe)->qe)
#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
(__hcb_qe)->cbfn = (__cbfn); \
(__hcb_qe)->cbarg = (__cbarg); \
if (!(__hcb_qe)->once) { \
list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
(__hcb_qe)->once = BFA_TRUE; \
} \
} 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)
/*
* PCI devices supported by the current BFA
*/
struct bfa_pciid_s {
u16 device_id;
u16 vendor_id;
};
extern char bfa_version[];
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_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_ctrl[BFI_IOC_MAX_CQS];
};
/*
* MSIX vector handlers
*/
#define BFA_MSIX_MAX_VECTORS 22
typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
struct bfa_msix_s {
int nvecs;
bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
};
/*
* Chip specific interfaces
*/
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, u32 ci);
void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
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;
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 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 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];
struct bfa_dma_s rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
struct bfa_iocfc_regs_s bfa_regs; /* BFA device registers */
struct bfa_hwif_s hwif;
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_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_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_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))
#define bfa_msix_get_rme_range(__bfa, __start, __end) \
((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
#define bfa_msix(__bfa, __vec) \
((__bfa)->msix.handler[__vec](__bfa, __vec))
/*
* FC specific IOC functions.
*/
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_pcidev_s *pcidev);
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, 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);
void bfa_msix_all(struct bfa_s *bfa, int vec);
void bfa_msix_reqq(struct bfa_s *bfa, int vec);
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_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_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,
u32 *maxvec);
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, 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_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_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
struct bfi_pbc_vport_s *pbc_vport);
/*
*----------------------------------------------------------------------
* BFA public interfaces
*----------------------------------------------------------------------
*/
#define bfa_stats(_mod, _stats) ((_mod)->stats._stats++)
#define bfa_ioc_get_stats(__bfa, __ioc_stats) \
bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
#define bfa_ioc_clear_stats(__bfa) \
bfa_ioc_clr_stats(&(__bfa)->ioc)
#define bfa_get_nports(__bfa) \
bfa_ioc_get_nports(&(__bfa)->ioc)
#define bfa_get_adapter_manufacturer(__bfa, __manufacturer) \
bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
#define bfa_get_adapter_model(__bfa, __model) \
bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
#define bfa_get_adapter_serial_num(__bfa, __serial_num) \
bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
#define bfa_get_adapter_fw_ver(__bfa, __fw_ver) \
bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver) \
bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
#define bfa_get_pci_chip_rev(__bfa, __chip_rev) \
bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
#define bfa_get_ioc_state(__bfa) \
bfa_ioc_get_state(&(__bfa)->ioc)
#define bfa_get_type(__bfa) \
bfa_ioc_get_type(&(__bfa)->ioc)
#define bfa_get_mac(__bfa) \
bfa_ioc_get_mac(&(__bfa)->ioc)
#define bfa_get_mfg_mac(__bfa) \
bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
#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_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_detach(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_isr_enable(struct bfa_s *bfa);
void bfa_isr_disable(struct bfa_s *bfa);
void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
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);
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);
#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \
bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
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__ */

2000
drivers/scsi/bfa/bfa_core.c Normal file

File diff suppressed because it is too large Load diff

366
drivers/scsi/bfa/bfa_cs.h Normal file
View file

@ -0,0 +1,366 @@
/*
* 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.
*/
/*
* bfa_cs.h BFA common services
*/
#ifndef __BFA_CS_H__
#define __BFA_CS_H__
#include "bfad_drv.h"
/*
* BFA TRC
*/
#ifndef BFA_TRC_MAX
#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 __BIG_ENDIAN
u16 fileno;
u16 line;
#else
u16 line;
u16 fileno;
#endif
u32 timestamp;
union {
struct {
u32 rsvd;
u32 u32;
} u32;
u64 u64;
} data;
};
struct bfa_trc_mod_s {
u32 head;
u32 tail;
u32 ntrc;
u32 stopped;
u32 ticks;
u32 rsvd[3];
struct bfa_trc_s trc[BFA_TRC_MAX];
};
enum {
BFA_TRC_HAL = 1, /* BFA modules */
BFA_TRC_FCS = 2, /* BFA FCS modules */
BFA_TRC_LDRV = 3, /* Linux driver modules */
BFA_TRC_CNA = 4, /* Common modules */
};
#define BFA_TRC_MOD_SH 10
#define BFA_TRC_MOD(__mod) ((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
/*
* Define a new tracing file (module). Module should match one defined above.
*/
#define BFA_TRC_FILE(__mod, __submod) \
static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
BFA_TRC_MOD(__mod))
#define bfa_trc32(_trcp, _data) \
__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
#define bfa_trc(_trcp, _data) \
__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
static inline void
bfa_trc_init(struct bfa_trc_mod_s *trcm)
{
trcm->head = trcm->tail = trcm->stopped = 0;
trcm->ntrc = BFA_TRC_MAX;
}
static inline void
bfa_trc_stop(struct bfa_trc_mod_s *trcm)
{
trcm->stopped = 1;
}
static inline void
__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
{
int tail = trcm->tail;
struct bfa_trc_s *trc = &trcm->trc[tail];
if (trcm->stopped)
return;
trc->fileno = (u16) fileno;
trc->line = (u16) line;
trc->data.u64 = data;
trc->timestamp = BFA_TRC_TS(trcm);
trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
if (trcm->tail == trcm->head)
trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
}
static inline void
__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
{
int tail = trcm->tail;
struct bfa_trc_s *trc = &trcm->trc[tail];
if (trcm->stopped)
return;
trc->fileno = (u16) fileno;
trc->line = (u16) line;
trc->data.u32.u32 = data;
trc->timestamp = BFA_TRC_TS(trcm);
trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
if (trcm->tail == trcm->head)
trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
}
#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)
/* BFA queue definitions */
#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
/*
* bfa_q_qe_init - to initialize a queue element
*/
#define bfa_q_qe_init(_qe) { \
bfa_q_next(_qe) = (struct list_head *) NULL; \
bfa_q_prev(_qe) = (struct list_head *) NULL; \
}
/*
* bfa_q_deq - dequeue an element from head of the queue
*/
#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));\
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
} \
} while (0)
/*
* bfa_q_deq_tail - dequeue an element from tail of the queue
*/
#define bfa_q_deq_tail(_q, _qe) { \
if (!list_empty(_q)) { \
*((struct list_head **) (_qe)) = bfa_q_prev(_q); \
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);\
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
} \
}
static inline int
bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
{
struct list_head *tqe;
tqe = bfa_q_next(q);
while (tqe != q) {
if (tqe == qe)
return 1;
tqe = bfa_q_next(tqe);
if (tqe == NULL)
break;
}
return 0;
}
#define bfa_q_is_on_q(_q, _qe) \
bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
/*
* @ BFA state machine interfaces
*/
typedef void (*bfa_sm_t)(void *sm, int event);
/*
* oc - object class eg. bfa_ioc
* st - state, eg. reset
* otype - object type, eg. struct bfa_ioc_s
* etype - object type, eg. enum ioc_event
*/
#define bfa_sm_state_decl(oc, st, otype, etype) \
static void oc ## _sm_ ## st(otype * fsm, etype event)
#define bfa_sm_set_state(_sm, _state) ((_sm)->sm = (bfa_sm_t)(_state))
#define bfa_sm_send_event(_sm, _event) ((_sm)->sm((_sm), (_event)))
#define bfa_sm_get_state(_sm) ((_sm)->sm)
#define bfa_sm_cmp_state(_sm, _state) ((_sm)->sm == (bfa_sm_t)(_state))
/*
* For converting from state machine function to state encoding.
*/
struct bfa_sm_table_s {
bfa_sm_t sm; /* state machine function */
int state; /* state machine encoding */
char *name; /* state name for display */
};
#define BFA_SM(_sm) ((bfa_sm_t)(_sm))
/*
* State machine with entry actions.
*/
typedef void (*bfa_fsm_t)(void *fsm, int event);
/*
* oc - object class eg. bfa_ioc
* st - state, eg. reset
* otype - object type, eg. struct bfa_ioc_s
* etype - object type, eg. enum ioc_event
*/
#define bfa_fsm_state_decl(oc, st, otype, etype) \
static void oc ## _sm_ ## st(otype * fsm, etype event); \
static void oc ## _sm_ ## st ## _entry(otype * fsm)
#define bfa_fsm_set_state(_fsm, _state) do { \
(_fsm)->fsm = (bfa_fsm_t)(_state); \
_state ## _entry(_fsm); \
} while (0)
#define bfa_fsm_send_event(_fsm, _event) ((_fsm)->fsm((_fsm), (_event)))
#define bfa_fsm_get_state(_fsm) ((_fsm)->fsm)
#define bfa_fsm_cmp_state(_fsm, _state) \
((_fsm)->fsm == (bfa_fsm_t)(_state))
static inline int
bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
{
int i = 0;
while (smt[i].sm && smt[i].sm != sm)
i++;
return smt[i].state;
}
/*
* @ Generic wait counter.
*/
typedef void (*bfa_wc_resume_t) (void *cbarg);
struct bfa_wc_s {
bfa_wc_resume_t wc_resume;
void *wc_cbarg;
int wc_count;
};
static inline void
bfa_wc_up(struct bfa_wc_s *wc)
{
wc->wc_count++;
}
static inline void
bfa_wc_down(struct bfa_wc_s *wc)
{
wc->wc_count--;
if (wc->wc_count == 0)
wc->wc_resume(wc->wc_cbarg);
}
/*
* Initialize a waiting counter.
*/
static inline void
bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
{
wc->wc_resume = wc_resume;
wc->wc_cbarg = wc_cbarg;
wc->wc_count = 0;
bfa_wc_up(wc);
}
/*
* Wait for counter to reach zero
*/
static inline void
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__ */

1287
drivers/scsi/bfa/bfa_defs.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,478 @@
/*
* 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_DEFS_FCS_H__
#define __BFA_DEFS_FCS_H__
#include "bfa_fc.h"
#include "bfa_defs_svc.h"
/*
* VF states
*/
enum bfa_vf_state {
BFA_VF_UNINIT = 0, /* fabric is not yet initialized */
BFA_VF_LINK_DOWN = 1, /* link is down */
BFA_VF_FLOGI = 2, /* flogi is in progress */
BFA_VF_AUTH = 3, /* authentication in progress */
BFA_VF_NOFABRIC = 4, /* fabric is not present */
BFA_VF_ONLINE = 5, /* login to fabric is complete */
BFA_VF_EVFP = 6, /* EVFP is in progress */
BFA_VF_ISOLATED = 7, /* port isolated due to vf_id mismatch */
};
/*
* VF statistics
*/
struct bfa_vf_stats_s {
u32 flogi_sent; /* Num FLOGIs sent */
u32 flogi_rsp_err; /* FLOGI response errors */
u32 flogi_acc_err; /* FLOGI accept errors */
u32 flogi_accepts; /* FLOGI accepts received */
u32 flogi_rejects; /* FLOGI rejects received */
u32 flogi_unknown_rsp; /* Unknown responses for FLOGI */
u32 flogi_alloc_wait; /* Allocation waits prior to sending FLOGI */
u32 flogi_rcvd; /* FLOGIs received */
u32 flogi_rejected; /* Incoming FLOGIs rejected */
u32 fabric_onlines; /* Internal fabric online notification sent
* to other modules */
u32 fabric_offlines; /* Internal fabric offline notification sent
* to other modules */
u32 resvd; /* padding for 64 bit alignment */
};
/*
* VF attributes returned in queries
*/
struct bfa_vf_attr_s {
enum bfa_vf_state state; /* VF state */
u32 rsvd;
wwn_t fabric_name; /* fabric name */
};
#define BFA_FCS_MAX_LPORTS 256
#define BFA_FCS_FABRIC_IPADDR_SZ 16
/*
* symbolic names for base port/virtual port
*/
#define BFA_SYMNAME_MAXLEN 128 /* 128 bytes */
struct bfa_lport_symname_s {
char symname[BFA_SYMNAME_MAXLEN];
};
/*
* Roles of FCS port:
* - FCP IM and FCP TM roles cannot be enabled together for a FCS port
* - Create multiple ports if both IM and TM functions required.
* - Atleast one role must be specified.
*/
enum bfa_lport_role {
BFA_LPORT_ROLE_FCP_IM = 0x01, /* FCP initiator role */
BFA_LPORT_ROLE_FCP_MAX = BFA_LPORT_ROLE_FCP_IM,
};
/*
* 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 */
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];
};
/*
* FCS port states
*/
enum bfa_lport_state {
BFA_LPORT_UNINIT = 0, /* PORT is not yet initialized */
BFA_LPORT_FDISC = 1, /* FDISC is in progress */
BFA_LPORT_ONLINE = 2, /* login to fabric is complete */
BFA_LPORT_OFFLINE = 3, /* No login to fabric */
};
/*
* FCS port type.
*/
enum bfa_lport_type {
BFA_LPORT_TYPE_PHYSICAL = 0,
BFA_LPORT_TYPE_VIRTUAL,
};
/*
* FCS port offline reason.
*/
enum bfa_lport_offline_reason {
BFA_LPORT_OFFLINE_UNKNOWN = 0,
BFA_LPORT_OFFLINE_LINKDOWN,
BFA_LPORT_OFFLINE_FAB_UNSUPPORTED, /* NPIV not supported by the
* fabric */
BFA_LPORT_OFFLINE_FAB_NORESOURCES,
BFA_LPORT_OFFLINE_FAB_LOGOUT,
};
/*
* FCS lport info.
*/
struct bfa_lport_info_s {
u8 port_type; /* bfa_lport_type_t : physical or
* virtual */
u8 port_state; /* one of bfa_lport_state values */
u8 offline_reason; /* one of bfa_lport_offline_reason_t
* values */
wwn_t port_wwn;
wwn_t node_wwn;
/*
* following 4 feilds are valid for Physical Ports only
*/
u32 max_vports_supp; /* Max supported vports */
u32 num_vports_inuse; /* Num of in use vports */
u32 max_rports_supp; /* Max supported rports */
u32 num_rports_inuse; /* Num of doscovered rports */
};
/*
* FCS port statistics
*/
struct bfa_lport_stats_s {
u32 ns_plogi_sent;
u32 ns_plogi_rsp_err;
u32 ns_plogi_acc_err;
u32 ns_plogi_accepts;
u32 ns_rejects; /* NS command rejects */
u32 ns_plogi_unknown_rsp;
u32 ns_plogi_alloc_wait;
u32 ns_retries; /* NS command retries */
u32 ns_timeouts; /* NS command timeouts */
u32 ns_rspnid_sent;
u32 ns_rspnid_accepts;
u32 ns_rspnid_rsp_err;
u32 ns_rspnid_rejects;
u32 ns_rspnid_alloc_wait;
u32 ns_rftid_sent;
u32 ns_rftid_accepts;
u32 ns_rftid_rsp_err;
u32 ns_rftid_rejects;
u32 ns_rftid_alloc_wait;
u32 ns_rffid_sent;
u32 ns_rffid_accepts;
u32 ns_rffid_rsp_err;
u32 ns_rffid_rejects;
u32 ns_rffid_alloc_wait;
u32 ns_gidft_sent;
u32 ns_gidft_accepts;
u32 ns_gidft_rsp_err;
u32 ns_gidft_rejects;
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
*/
u32 ms_retries; /* MS command retries */
u32 ms_timeouts; /* MS command timeouts */
u32 ms_plogi_sent;
u32 ms_plogi_rsp_err;
u32 ms_plogi_acc_err;
u32 ms_plogi_accepts;
u32 ms_rejects; /* MS command rejects */
u32 ms_plogi_unknown_rsp;
u32 ms_plogi_alloc_wait;
u32 num_rscn; /* Num of RSCN received */
u32 num_portid_rscn;/* Num portid format RSCN
* received */
u32 uf_recvs; /* Unsolicited recv frames */
u32 uf_recv_drops; /* Dropped received frames */
u32 plogi_rcvd; /* Received plogi */
u32 prli_rcvd; /* Received prli */
u32 adisc_rcvd; /* Received adisc */
u32 prlo_rcvd; /* Received prlo */
u32 logo_rcvd; /* Received logo */
u32 rpsc_rcvd; /* Received rpsc */
u32 un_handled_els_rcvd; /* Received unhandled ELS */
u32 rport_plogi_timeouts; /* Rport plogi retry timeout count */
u32 rport_del_max_plogi_retry; /* Deleted rport
* (max retry of plogi) */
};
/*
* BFA port attribute returned in queries
*/
struct bfa_lport_attr_s {
enum bfa_lport_state state; /* port state */
u32 pid; /* port ID */
struct bfa_lport_cfg_s port_cfg; /* port configuration */
enum bfa_port_type port_type; /* current topology */
u32 loopback; /* cable is externally looped back */
wwn_t fabric_name; /* attached switch's nwwn */
u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /* attached
* fabric's ip addr */
mac_t fpma_mac; /* Lport's FPMA Mac address */
u16 authfail; /* auth failed state */
};
/*
* VPORT states
*/
enum bfa_vport_state {
BFA_FCS_VPORT_UNINIT = 0,
BFA_FCS_VPORT_CREATED = 1,
BFA_FCS_VPORT_OFFLINE = 1,
BFA_FCS_VPORT_FDISC_SEND = 2,
BFA_FCS_VPORT_FDISC = 3,
BFA_FCS_VPORT_FDISC_RETRY = 4,
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,
};
/*
* vport statistics
*/
struct bfa_vport_stats_s {
struct bfa_lport_stats_s port_stats; /* base class (port) stats */
/*
* TODO - remove
*/
u32 fdisc_sent; /* num fdisc sent */
u32 fdisc_accepts; /* fdisc accepts */
u32 fdisc_retries; /* fdisc retries */
u32 fdisc_timeouts; /* fdisc timeouts */
u32 fdisc_rsp_err; /* fdisc response error */
u32 fdisc_acc_bad; /* bad fdisc accepts */
u32 fdisc_rejects; /* fdisc rejects */
u32 fdisc_unknown_rsp;
/*
*!< fdisc rsp unknown error
*/
u32 fdisc_alloc_wait;/* fdisc req (fcxp)alloc wait */
u32 logo_alloc_wait;/* logo req (fcxp) alloc wait */
u32 logo_sent; /* logo sent */
u32 logo_accepts; /* logo accepts */
u32 logo_rejects; /* logo rejects */
u32 logo_rsp_err; /* logo rsp errors */
u32 logo_unknown_rsp;
/* logo rsp unknown errors */
u32 fab_no_npiv; /* fabric does not support npiv */
u32 fab_offline; /* offline events from fab SM */
u32 fab_online; /* online events from fab SM */
u32 fab_cleanup; /* cleanup request from fab SM */
u32 rsvd;
};
/*
* BFA vport attribute returned in queries
*/
struct bfa_vport_attr_s {
struct bfa_lport_attr_s port_attr; /* base class (port) attributes */
enum bfa_vport_state vport_state; /* vport state */
u32 rsvd;
};
/*
* FCS remote port states
*/
enum bfa_rport_state {
BFA_RPORT_UNINIT = 0, /* PORT is not yet initialized */
BFA_RPORT_OFFLINE = 1, /* rport is offline */
BFA_RPORT_PLOGI = 2, /* PLOGI to rport is in progress */
BFA_RPORT_ONLINE = 3, /* login to rport is complete */
BFA_RPORT_PLOGI_RETRY = 4, /* retrying login to rport */
BFA_RPORT_NSQUERY = 5, /* nameserver query */
BFA_RPORT_ADISC = 6, /* ADISC authentication */
BFA_RPORT_LOGO = 7, /* logging out with rport */
BFA_RPORT_LOGORCV = 8, /* handling LOGO from rport */
BFA_RPORT_NSDISC = 9, /* re-discover rport */
};
/*
* Rport Scsi Function : Initiator/Target.
*/
enum bfa_rport_function {
BFA_RPORT_INITIATOR = 0x01, /* SCSI Initiator */
BFA_RPORT_TARGET = 0x02, /* SCSI Target */
};
/*
* port/node symbolic names for rport
*/
#define BFA_RPORT_SYMNAME_MAXLEN 255
struct bfa_rport_symname_s {
char symname[BFA_RPORT_SYMNAME_MAXLEN];
};
/*
* FCS remote port statistics
*/
struct bfa_rport_stats_s {
u32 offlines; /* remote port offline count */
u32 onlines; /* remote port online count */
u32 rscns; /* RSCN affecting rport */
u32 plogis; /* plogis sent */
u32 plogi_accs; /* plogi accepts */
u32 plogi_timeouts; /* plogi timeouts */
u32 plogi_rejects; /* rcvd plogi rejects */
u32 plogi_failed; /* local failure */
u32 plogi_rcvd; /* plogis rcvd */
u32 prli_rcvd; /* inbound PRLIs */
u32 adisc_rcvd; /* ADISCs received */
u32 adisc_rejects; /* recvd ADISC rejects */
u32 adisc_sent; /* ADISC requests sent */
u32 adisc_accs; /* ADISC accepted by rport */
u32 adisc_failed; /* ADISC failed (no response) */
u32 adisc_rejected; /* ADISC rejected by us */
u32 logos; /* logos sent */
u32 logo_accs; /* LOGO accepts from rport */
u32 logo_failed; /* LOGO failures */
u32 logo_rejected; /* LOGO rejects from rport */
u32 logo_rcvd; /* LOGO from remote port */
u32 rpsc_rcvd; /* RPSC received */
u32 rpsc_rejects; /* recvd RPSC rejects */
u32 rpsc_sent; /* RPSC requests sent */
u32 rpsc_accs; /* RPSC accepted by rport */
u32 rpsc_failed; /* RPSC failed (no response) */
u32 rpsc_rejected; /* RPSC rejected by us */
u32 rjt_insuff_res; /* LS RJT with insuff resources */
struct bfa_rport_hal_stats_s hal_stats; /* BFA rport stats */
};
/*
* FCS remote port attributes returned in queries
*/
struct bfa_rport_attr_s {
wwn_t nwwn; /* node wwn */
wwn_t pwwn; /* port wwn */
enum fc_cos cos_supported; /* supported class of services */
u32 pid; /* port ID */
u32 df_sz; /* Max payload size */
enum bfa_rport_state state; /* Rport State machine state */
enum fc_cos fc_cos; /* FC classes of services */
bfa_boolean_t cisc; /* CISC capable device */
struct bfa_rport_symname_s symname; /* Symbolic Name */
enum bfa_rport_function scsi_function; /* Initiator/Target */
struct bfa_rport_qos_attr_s qos_attr; /* qos attributes */
enum bfa_port_speed curr_speed; /* operating speed got from
* RPSC ELS. UNKNOWN, if RPSC
* is not supported */
bfa_boolean_t trl_enforced; /* TRL enforced ? TRUE/FALSE */
enum bfa_port_speed assigned_speed; /* Speed assigned by the user.
* will be used if RPSC is not
* supported by the rport */
};
struct bfa_rport_remote_link_stats_s {
u32 lfc; /* Link Failure Count */
u32 lsyc; /* Loss of Synchronization Count */
u32 lsic; /* Loss of Signal Count */
u32 pspec; /* Primitive Sequence Protocol Error Count */
u32 itwc; /* Invalid Transmission Word Count */
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
/*
* FCS itnim states
*/
enum bfa_itnim_state {
BFA_ITNIM_OFFLINE = 0, /* offline */
BFA_ITNIM_PRLI_SEND = 1, /* prli send */
BFA_ITNIM_PRLI_SENT = 2, /* prli sent */
BFA_ITNIM_PRLI_RETRY = 3, /* prli retry */
BFA_ITNIM_HCB_ONLINE = 4, /* online callback */
BFA_ITNIM_ONLINE = 5, /* online */
BFA_ITNIM_HCB_OFFLINE = 6, /* offline callback */
BFA_ITNIM_INITIATIOR = 7, /* initiator */
};
/*
* FCS remote port statistics
*/
struct bfa_itnim_stats_s {
u32 onlines; /* num rport online */
u32 offlines; /* num rport offline */
u32 prli_sent; /* num prli sent out */
u32 fcxp_alloc_wait;/* num fcxp alloc waits */
u32 prli_rsp_err; /* num prli rsp errors */
u32 prli_rsp_acc; /* num prli rsp accepts */
u32 initiator; /* rport is an initiator */
u32 prli_rsp_parse_err; /* prli rsp parsing errors */
u32 prli_rsp_rjt; /* num prli rsp rejects */
u32 timeout; /* num timeouts detected */
u32 sler; /* num sler notification from BFA */
u32 rsvd; /* padding for 64 bit alignment */
};
/*
* FCS itnim attributes returned in queries
*/
struct bfa_itnim_attr_s {
enum bfa_itnim_state state; /* FCS itnim state */
u8 retry; /* data retransmision support */
u8 task_retry_id; /* task retry ident support */
u8 rec_support; /* REC supported */
u8 conf_comp; /* confirmed completion supp */
};
#endif /* __BFA_DEFS_FCS_H__ */

File diff suppressed because it is too large Load diff

1628
drivers/scsi/bfa/bfa_fc.h Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,328 @@
/*
* 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.
*/
/*
* fcbuild.h - FC link service frame building and parsing routines
*/
#ifndef __FCBUILD_H__
#define __FCBUILD_H__
#include "bfad_drv.h"
#include "bfa_fc.h"
#include "bfa_defs_fcs.h"
/*
* Utility Macros/functions
*/
#define wwn_is_equal(_wwn1, _wwn2) \
(memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
/*
* Given the fc response length, this routine will return
* the length of the actual payload bytes following the CT header.
*
* Assumes the input response length does not include the crc, eof, etc.
*/
static inline u32
fc_get_ctresp_pyld_len(u32 resp_len)
{
return resp_len - sizeof(struct ct_hdr_s);
}
/*
* Convert bfa speed to rpsc speed value.
*/
static inline enum bfa_port_speed
fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
{
switch (speed) {
case RPSC_OP_SPEED_1G:
return BFA_PORT_SPEED_1GBPS;
case RPSC_OP_SPEED_2G:
return BFA_PORT_SPEED_2GBPS;
case RPSC_OP_SPEED_4G:
return BFA_PORT_SPEED_4GBPS;
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;
default:
return BFA_PORT_SPEED_UNKNOWN;
}
}
/*
* Convert RPSC speed to bfa speed value.
*/
static inline enum fc_rpsc_op_speed
fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
{
switch (op_speed) {
case BFA_PORT_SPEED_1GBPS:
return RPSC_OP_SPEED_1G;
case BFA_PORT_SPEED_2GBPS:
return RPSC_OP_SPEED_2G;
case BFA_PORT_SPEED_4GBPS:
return RPSC_OP_SPEED_4G;
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;
default:
return RPSC_OP_SPEED_NOT_EST;
}
}
enum fc_parse_status {
FC_PARSE_OK = 0,
FC_PARSE_FAILURE = 1,
FC_PARSE_BUSY = 2,
FC_PARSE_LEN_INVAL,
FC_PARSE_ACC_INVAL,
FC_PARSE_PWWN_NOT_EQUAL,
FC_PARSE_NWWN_NOT_EQUAL,
FC_PARSE_RXSZ_INVAL,
FC_PARSE_NOT_FCP,
FC_PARSE_OPAFLAG_INVAL,
FC_PARSE_RPAFLAG_INVAL,
FC_PARSE_OPA_INVAL,
FC_PARSE_RPA_INVAL,
};
struct fc_templates_s {
struct fchs_s fc_els_req;
struct fchs_s fc_bls_req;
struct fc_logi_s plogi;
struct fc_rrq_s rrq;
};
void fcbuild_init(void);
u16 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);
u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name,
u16 pdu_size);
u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
u32 s_id, __be16 ox_id,
wwn_t port_name, wwn_t node_name,
u16 pdu_size,
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, u16 bb_cr);
enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
u16 ox_id);
enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
u32 s_id, u16 ox_id, u16 rrq_oxid);
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);
u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 ox_id, u8 *fc4_bitmap,
u32 bitmap_size);
u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 ox_id, wwn_t port_name);
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 bb_cr);
u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
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,
u32 host_dap, wwn_t node_name, wwn_t port_name);
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, __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, __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, __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, __be16 ox_id,
enum bfa_lport_role role);
u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
u32 d_id, u32 s_id, u16 ox_id,
u32 data_format);
u16 fc_rnid_acc_build(struct fchs_s *fchs,
struct fc_rnid_acc_s *rnid_acc, u32 d_id, 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);
u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
u32 d_id, u32 s_id, u32 *pid_list, u16 npids);
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,
__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);
u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u32 port_id, wwn_t port_name);
u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u32 port_id, wwn_t node_name);
u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u32 port_id, u32 cos);
u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u32 port_id, u8 port_type);
u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u32 port_id);
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, __be16 ox_id);
u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 cmd_code);
u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
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,
__be16 ox_id);
enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
wwn_t port_name);
enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
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, __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, __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, __be16 ox_id, int num_pages);
u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name,
u16 pdu_size);
u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
u16 ox_id, int num_pages);
u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
u16 ox_id, int num_pages, enum fc_tprlo_type tprlo_type,
u32 tpr_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,
__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);
u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
u16 ox_id);
#endif

3936
drivers/scsi/bfa/bfa_fcpim.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,429 @@
/*
* 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_FCPIM_H__
#define __BFA_FCPIM_H__
#include "bfa.h"
#include "bfa_svc.h"
#include "bfi_ms.h"
#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
#define BFA_IOIM_MIN 8
#define BFA_IOIM_MAX 2000
#define BFA_TSKIM_MIN 4
#define BFA_TSKIM_MAX 512
#define BFA_FCPIM_PATHTOV_DEF (30 * 1000) /* in millisecs */
#define BFA_FCPIM_PATHTOV_MAX (90 * 1000) /* in millisecs */
#define bfa_itnim_ioprofile_update(__itnim, __index) \
(__itnim->ioprofile.iocomps[__index]++)
#define BFA_IOIM_RETRY_TAG_OFFSET 11
#define BFA_IOIM_IOTAG_MASK 0x07ff /* 2K IOs */
#define BFA_IOIM_RETRY_MAX 7
/* Buckets are are 512 bytes to 2MB */
static inline u32
bfa_ioim_get_index(u32 n) {
int pos = 0;
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 >= 1 << 1)
pos += 1;
return (n == 0) ? (0) : pos;
}
/*
* forward declarations
*/
struct bfa_ioim_s;
struct bfa_tskim_s;
struct bfad_ioim_s;
struct bfad_tskim_s;
typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
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;
int num_itnims;
int num_tskim_reqs;
u32 path_tov;
u16 q_depth;
u8 reqq; /* Request queue to be used */
struct list_head itnim_q; /* queue of active itnim */
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;
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;
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)
*/
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_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 */
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 */
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 */
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 */
};
/*
* BFA Task management command (initiator mode)
*/
struct bfa_tskim_s {
struct list_head qe;
bfa_sm_t sm;
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 */
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_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 bfi_mhdr_s mhdr; /* pre-built mhdr */
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 */
struct list_head io_cleanup_q; /* IO being cleaned up */
struct list_head tsk_q; /* queue of active TM commands */
struct list_head delay_comp_q; /* queue of failed inflight cmds */
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_reqq_wait_s reqq_wait; /* to wait for room in reqq */
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(_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_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.fcp_mod.fcpim.io_profile_start_time)
#define bfa_fcpim_get_io_profile(_bfa) \
((_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_maxretry_reached(struct bfa_ioim_s *ioim)
{
uint16_t k = ioim->iotag >> BFA_IOIM_RETRY_TAG_OFFSET;
if (k < BFA_IOIM_RETRY_MAX)
return BFA_FALSE;
return BFA_TRUE;
}
/*
* function prototypes
*/
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);
void bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
void bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
struct bfa_tskim_s *tskim);
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_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);
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);
/*
* bfa fcpim module API functions
*/
void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
u16 bfa_fcpim_path_tov_get(struct bfa_s *bfa);
u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa);
bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
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_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_s *)(BFA_FCPIM(__bfa)))->ioredirect)
#define bfa_fcpim_get_next_reqq(__bfa, __qid) \
{ \
struct bfa_fcpim_s *__fcpim = BFA_FCPIM(__bfa); \
__fcpim->reqq++; \
__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1); \
*(__qid) = __fcpim->reqq; \
}
#define bfa_iocfc_map_msg_to_qid(__msg, __qid) \
*(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1));
/*
* 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_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().
*/
void bfa_cb_itnim_online(void *itnim);
/*
* 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.
* 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.
*/
void bfa_cb_itnim_sler(void *itnim);
/*
* bfa ioim API functions
*/
struct bfa_ioim_s *bfa_ioim_alloc(struct bfa_s *bfa,
struct bfad_ioim_s *dio,
struct bfa_itnim_s *itnim,
u16 nsgles);
void bfa_ioim_free(struct bfa_ioim_s *ioim);
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.
*
* @param[in] dio driver IO structure
* @param[in] io_status IO completion status
* @param[in] scsi_status SCSI status returned by target
* @param[in] sns_len SCSI sense length, 0 if none
* @param[in] sns_info SCSI sense data, if any
* @param[in] residue Residual length
*
* @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);
/*
* I/O good completion notification.
*/
void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
/*
* I/O abort completion notification
*/
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, 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__ */

1712
drivers/scsi/bfa/bfa_fcs.c Normal file

File diff suppressed because it is too large Load diff

883
drivers/scsi/bfa/bfa_fcs.h Normal file
View file

@ -0,0 +1,883 @@
/*
* 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_FCS_H__
#define __BFA_FCS_H__
#include "bfa_cs.h"
#include "bfa_defs.h"
#include "bfa_defs_fcs.h"
#include "bfa_modules.h"
#include "bfa_fc.h"
#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
*/
enum {
BFA_TRC_FCS_FCS = 1,
BFA_TRC_FCS_PORT = 2,
BFA_TRC_FCS_RPORT = 3,
BFA_TRC_FCS_FCPIM = 4,
};
struct bfa_fcs_s;
#define __fcs_min_cfg(__fcs) ((__fcs)->min_cfg)
#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_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 */
struct bfa_timer_s timer;
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;
};
struct bfa_fcs_lport_scn_s {
bfa_sm_t sm; /* state machine */
struct bfa_timer_s timer;
struct bfa_fcs_lport_s *port; /* parent port */
struct bfa_fcxp_s *fcxp;
struct bfa_fcxp_wqe_s fcxp_wqe;
};
struct bfa_fcs_lport_fdmi_s {
bfa_sm_t sm; /* state machine */
struct bfa_timer_s timer;
struct bfa_fcs_lport_ms_s *ms; /* parent ms */
struct bfa_fcxp_s *fcxp;
struct bfa_fcxp_wqe_s fcxp_wqe;
u8 retry_cnt; /* retry count */
u8 rsvd[3];
};
struct bfa_fcs_lport_ms_s {
bfa_sm_t sm; /* state machine */
struct bfa_timer_s timer;
struct bfa_fcs_lport_s *port; /* parent port */
struct bfa_fcxp_s *fcxp;
struct bfa_fcxp_wqe_s fcxp_wqe;
struct bfa_fcs_lport_fdmi_s fdmi; /* FDMI component of MS */
u8 retry_cnt; /* retry count */
u8 rsvd[3];
};
struct bfa_fcs_lport_fab_s {
struct bfa_fcs_lport_ns_s ns; /* NS component of port */
struct bfa_fcs_lport_scn_s scn; /* scn component of port */
struct bfa_fcs_lport_ms_s ms; /* MS component of port */
};
#define MAX_ALPA_COUNT 127
struct bfa_fcs_lport_loop_s {
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;
__be16 reply_oxid; /* ox_id from the req flogi to be
*used in flogi acc */
wwn_t rem_port_wwn; /* Attached port's wwn */
};
union bfa_fcs_lport_topo_u {
struct bfa_fcs_lport_fab_s pfab;
struct bfa_fcs_lport_loop_s ploop;
struct bfa_fcs_lport_n2n_s pn2n;
};
struct bfa_fcs_lport_s {
struct list_head qe; /* used by port/vport */
bfa_sm_t sm; /* state machine */
struct bfa_fcs_fabric_s *fabric; /* parent fabric */
struct bfa_lport_cfg_s port_cfg; /* port configuration */
struct bfa_timer_s link_timer; /* timer for link offline */
u32 pid:24; /* FC address */
u8 lp_tag; /* lport tag */
u16 num_rports; /* Num of r-ports */
struct list_head rport_q; /* queue of discovered r-ports */
struct bfa_fcs_s *fcs; /* FCS instance */
union bfa_fcs_lport_topo_u port_topo; /* fabric/loop/n2n details */
struct bfad_port_s *bfad_port; /* driver peer instance */
struct bfa_fcs_vport_s *vport; /* NULL for base ports */
struct bfa_fcxp_s *fcxp;
struct bfa_fcxp_wqe_s fcxp_wqe;
struct bfa_lport_stats_s stats;
struct bfa_wc_s wc; /* waiting counter for events */
};
#define BFA_FCS_GET_HAL_FROM_PORT(port) (port->fcs->bfa)
#define BFA_FCS_GET_NS_FROM_PORT(port) (&port->port_topo.pfab.ns)
#define BFA_FCS_GET_SCN_FROM_PORT(port) (&port->port_topo.pfab.scn)
#define BFA_FCS_GET_MS_FROM_PORT(port) (&port->port_topo.pfab.ms)
#define BFA_FCS_GET_FDMI_FROM_PORT(port) (&port->port_topo.pfab.ms.fdmi)
#define BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
(port->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
/*
* forward declaration
*/
struct bfad_vf_s;
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,
};
struct bfa_fcs_fabric_s {
struct list_head qe; /* queue element */
bfa_sm_t sm; /* state machine */
struct bfa_fcs_s *fcs; /* FCS instance */
struct bfa_fcs_lport_s bport; /* base logical port */
enum bfa_fcs_fabric_type fab_type; /* fabric type */
enum bfa_port_type oper_type; /* current link topology */
u8 is_vf; /* is virtual fabric? */
u8 is_npiv; /* is NPIV supported ? */
u8 is_auth; /* is Security/Auth supported ? */
u16 bb_credit; /* BB credit from fabric */
u16 vf_id; /* virtual fabric ID */
u16 num_vports; /* num vports */
u16 rsvd;
struct list_head vport_q; /* queue of virtual ports */
struct list_head vf_q; /* queue of virtual fabrics */
struct bfad_vf_s *vf_drv; /* driver vf structure */
struct bfa_timer_s link_timer; /* Link Failure timer. Vport */
wwn_t fabric_name; /* attached fabric name */
bfa_boolean_t auth_reqd; /* authentication required */
struct bfa_timer_s delay_timer; /* delay timer */
union {
u16 swp_vfid;/* switch port VF id */
} event_arg;
struct bfa_wc_s wc; /* wait counter for delete */
struct bfa_vf_stats_s stats; /* fabric/vf stats */
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)
#define bfa_fcs_fabric_is_switched(__f) \
((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
/*
* The design calls for a single implementation of base fabric and vf.
*/
#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
struct bfa_vf_event_s {
u32 undefined;
};
struct bfa_fcs_s;
struct bfa_fcs_fabric_s;
/*
* @todo : need to move to a global config file.
* Maximum Rports supported per port (physical/logical).
*/
#define BFA_FCS_MAX_RPORTS_SUPP 256 /* @todo : tentative value */
#define bfa_fcs_lport_t struct bfa_fcs_lport_s
/*
* Symbolic Name related defines
* Total bytes 255.
* Physical Port's symbolic name 128 bytes.
* For Vports, Vport's symbolic name is appended to the Physical port's
* Symbolic Name.
*
* Physical Port's symbolic name Format : (Total 128 bytes)
* Adapter Model number/name : 16 bytes
* Driver Version : 10 bytes
* Host Machine Name : 30 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 16
#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 10
#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 30
#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 44
#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16
/*
* Get FC port ID for a logical port.
*/
#define bfa_fcs_lport_get_fcid(_lport) ((_lport)->pid)
#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) \
((_lport) ? (_lport)->num_rports : 0)
static inline struct bfad_port_s *
bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)
{
return port->bfad_port;
}
#define bfa_fcs_lport_get_opertype(_lport) ((_lport)->fabric->oper_type)
#define bfa_fcs_lport_get_fabric_name(_lport) ((_lport)->fabric->fabric_name)
#define bfa_fcs_lport_get_fabric_ipaddr(_lport) \
((_lport)->fabric->fabric_ip_addr)
/*
* bfa fcs port public functions
*/
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_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,
struct bfa_lport_attr_s *port_attr);
void bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
struct bfa_lport_stats_s *port_stats);
void bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port);
enum bfa_port_speed bfa_fcs_lport_get_rport_max_speed(
struct bfa_fcs_lport_s *port);
/* MS FCS routines */
void bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port);
void bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port);
void bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port);
void bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port);
/* FDMI FCS routines */
void bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms);
void bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms);
void bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms);
void bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, struct fchs_s *fchs,
u16 len);
void bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
u16 vf_id, struct bfa_fcs_vport_s *vport);
void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
struct bfa_lport_cfg_s *port_cfg);
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_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_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 */
bfa_sm_t sm; /* state machine */
bfa_fcs_lport_t lport; /* logical port */
struct bfa_timer_s timer;
struct bfad_vport_s *vport_drv; /* Driver private */
struct bfa_vport_stats_s vport_stats; /* vport statistics */
struct bfa_lps_s *lps; /* Lport login service*/
int fdisc_retries;
};
#define bfa_fcs_vport_get_port(vport) \
((struct bfa_fcs_lport_s *)(&vport->port))
/*
* bfa fcs vport public functions
*/
bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
struct bfa_fcs_s *fcs, u16 vf_id,
struct bfa_lport_cfg_s *port_cfg,
struct bfad_vport_s *vport_drv);
bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport,
struct bfa_fcs_s *fcs, u16 vf_id,
struct bfa_lport_cfg_s *port_cfg,
struct bfad_vport_s *vport_drv);
bfa_boolean_t bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport);
bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
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);
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);
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)
/*
* forward declarations
*/
struct bfad_rport_s;
struct bfa_fcs_itnim_s;
struct bfa_fcs_tin_s;
struct bfa_fcs_iprp_s;
/* Rport Features (RPF) */
struct bfa_fcs_rpf_s {
bfa_sm_t sm; /* state machine */
struct bfa_fcs_rport_s *rport; /* parent rport */
struct bfa_timer_s timer; /* general purpose timer */
struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */
struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */
int rpsc_retries; /* max RPSC retry attempts */
enum bfa_port_speed rpsc_speed;
/* Current Speed from RPSC. O if RPSC fails */
enum bfa_port_speed assigned_speed;
/*
* Speed assigned by the user. will be used if RPSC is
* not supported by the rport.
*/
};
struct bfa_fcs_rport_s {
struct list_head qe; /* used by port/vport */
struct bfa_fcs_lport_s *port; /* parent FCS port */
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 */
__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 */
bfa_sm_t sm; /* state machine */
struct bfa_timer_s timer; /* general purpose timer */
struct bfa_fcs_itnim_s *itnim; /* ITN initiator mode role */
struct bfa_fcs_tin_s *tin; /* ITN initiator mode role */
struct bfa_fcs_iprp_s *iprp; /* IP/FC role */
struct bfa_rport_s *bfa_rport; /* BFA Rport */
struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */
int plogi_retries; /* max plogi retry attempts */
int ns_retries; /* max NS query retry attempts */
struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */
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 *
bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
{
return rport->bfa_rport;
}
/*
* bfa fcs rport API functions
*/
void bfa_fcs_rport_get_attr(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_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_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,
struct fchs_s *rx_fchs,
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_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id);
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);
struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(
struct bfa_fcs_lport_s *port, wwn_t wwn);
void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
/*
* forward declarations
*/
struct bfad_itnim_s;
struct bfa_fcs_itnim_s {
bfa_sm_t sm; /* state machine */
struct bfa_fcs_rport_s *rport; /* parent remote rport */
struct bfad_itnim_s *itnim_drv; /* driver peer instance */
struct bfa_fcs_s *fcs; /* fcs instance */
struct bfa_timer_s timer; /* timer functions */
struct bfa_itnim_s *bfa_itnim; /* BFA itnim struct */
u32 prli_retries; /* max prli retry attempts */
bfa_boolean_t seq_rec; /* seq recovery support */
bfa_boolean_t rec_support; /* REC supported */
bfa_boolean_t conf_comp; /* FCP_CONF support */
bfa_boolean_t task_retry_id; /* task retry id supp */
struct bfa_fcxp_wqe_s fcxp_wqe; /* wait qelem for fcxp */
struct bfa_fcxp_s *fcxp; /* FCXP in use */
struct bfa_itnim_stats_s stats; /* itn statistics */
};
#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)
{
return itnim->rport->port->bfad_port;
}
static inline struct bfa_fcs_lport_s *
bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
{
return itnim->rport->port;
}
static inline wwn_t
bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
{
return itnim->rport->nwwn;
}
static inline wwn_t
bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
{
return itnim->rport->pwwn;
}
static inline u32
bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
{
return itnim->rport->pid;
}
static inline u32
bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
{
return itnim->rport->maxfrsize;
}
static inline enum fc_cos
bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
{
return itnim->rport->fc_cos;
}
static inline struct bfad_itnim_s *
bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
{
return itnim->itnim_drv;
}
static inline struct bfa_itnim_s *
bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
{
return itnim->bfa_itnim;
}
/*
* bfa fcs FCP Initiator mode API functions
*/
void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
struct bfa_itnim_attr_s *attr);
void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
struct bfa_itnim_stats_s *stats);
struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port,
wwn_t rpwwn);
bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
struct bfa_itnim_attr_s *attr);
bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
struct bfa_itnim_stats_s *stats);
bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port,
wwn_t rpwwn);
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_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_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
* sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
* on this the size has been reduced to 16 bytes from the standard's 64 bytes.
*/
struct bfa_fcs_fdmi_hba_attr_s {
wwn_t node_name;
u8 manufacturer[64];
u8 serial_num[64];
u8 model[16];
u8 model_desc[128];
u8 hw_version[8];
u8 driver_version[BFA_VERSION_LEN];
u8 option_rom_ver[BFA_VERSION_LEN];
u8 fw_version[BFA_VERSION_LEN];
u8 os_name[256];
__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[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 {
struct {
u32 untagged; /* untagged receive frames */
u32 tagged; /* tagged receive frames */
u32 vfid_unknown; /* VF id is unknown */
} uf;
};
struct bfa_fcs_driver_info_s {
u8 version[BFA_VERSION_LEN]; /* Driver Version */
u8 host_machine_name[BFA_FCS_OS_STR_LEN];
u8 host_os_name[BFA_FCS_OS_STR_LEN]; /* OS name and version */
u8 host_os_patch[BFA_FCS_OS_STR_LEN]; /* patch or service pack */
u8 os_device_name[BFA_FCS_OS_STR_LEN]; /* Driver Device Name */
};
struct bfa_fcs_s {
struct bfa_s *bfa; /* corresponding BFA bfa instance */
struct bfad_s *bfad; /* corresponding BDA driver instance */
struct bfa_trc_mod_s *trcmod; /* tracing module */
bfa_boolean_t vf_enabled; /* VF mode is enabled */
bfa_boolean_t fdmi_enabled; /* FDMI is enabled */
bfa_boolean_t min_cfg; /* min cfg enabled/disabled */
u16 port_vfid; /* port default VF ID */
struct bfa_fcs_driver_info_s driver_info;
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 */
};
/*
* bfa fcs API functions
*/
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_exit(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);
void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
/*
* fabric protected interface functions
*/
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_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);
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);
void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
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
*/
/*
* fcb Main fcs callbacks
*/
struct bfad_port_s;
struct bfad_vf_s;
struct bfad_vport_s;
struct bfad_rport_s;
/*
* lport callbacks
*/
struct bfad_port_s *bfa_fcb_lport_new(struct bfad_s *bfad,
struct bfa_fcs_lport_s *port,
enum bfa_lport_role roles,
struct bfad_vf_s *vf_drv,
struct bfad_vport_s *vp_drv);
/*
* vport callbacks
*/
void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s);
/*
* rport callbacks
*/
bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
struct bfa_fcs_rport_s **rport,
struct bfad_rport_s **rport_drv);
/*
* itnim callbacks
*/
void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
struct bfad_itnim_s **itnim_drv);
void bfa_fcb_itnim_free(struct bfad_s *bfad,
struct bfad_itnim_s *itnim_drv);
void bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
void bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
#endif /* __BFA_FCS_H__ */

View file

@ -0,0 +1,839 @@
/*
* 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.
*/
/*
* fcpim.c - FCP initiator mode i-t nexus state machine
*/
#include "bfad_drv.h"
#include "bfa_fcs.h"
#include "bfa_fcbuild.h"
#include "bfad_im.h"
BFA_TRC_FILE(FCS, FCPIM);
/*
* forward declarations
*/
static void bfa_fcs_itnim_timeout(void *arg);
static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
static void bfa_fcs_itnim_send_prli(void *itnim_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
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);
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);
static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
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,
enum bfa_fcs_itnim_event event);
static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
static struct bfa_sm_table_s itnim_sm_table[] = {
{BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
{BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
{BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
{BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
{BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
{BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
{BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
{BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
};
/*
* fcs_itnim_sm FCS itnim state machine
*/
static void
bfa_fcs_itnim_sm_offline(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_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_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);
break;
case BFA_FCS_ITNIM_SM_DELETE:
bfa_fcs_itnim_free(itnim);
break;
default:
bfa_sm_fault(itnim->fcs, event);
}
}
static void
bfa_fcs_itnim_sm_prli_send(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_FRMSENT:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
break;
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_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_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
bfa_fcs_itnim_free(itnim);
break;
default:
bfa_sm_fault(itnim->fcs, event);
}
}
static void
bfa_fcs_itnim_sm_prli(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_RSP_OK:
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_hal_rport_online);
bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
break;
case BFA_FCS_ITNIM_SM_RSP_ERROR:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
bfa_fcs_itnim_timeout, 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_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:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_fcxp_discard(itnim->fcxp);
bfa_fcs_itnim_free(itnim);
break;
default:
bfa_sm_fault(itnim->fcs, event);
}
}
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)
{
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
switch (event) {
case BFA_FCS_ITNIM_SM_TIMEOUT:
if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
itnim->prli_retries++;
bfa_trc(itnim->fcs, itnim->prli_retries);
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
bfa_fcs_itnim_send_prli(itnim, NULL);
} else {
/* invoke target offline */
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
}
break;
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_timer_stop(&itnim->timer);
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:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_timer_stop(&itnim->timer);
bfa_fcs_itnim_free(itnim);
break;
default:
bfa_sm_fault(itnim->fcs, event);
}
}
static void
bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event)
{
struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
char lpwwn_buf[BFA_STRING_32];
char rpwwn_buf[BFA_STRING_32];
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
switch (event) {
case BFA_FCS_ITNIM_SM_HCB_ONLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
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, 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_hcb_offline);
bfa_itnim_offline(itnim->bfa_itnim);
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_online(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event)
{
struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
char lpwwn_buf[BFA_STRING_32];
char rpwwn_buf[BFA_STRING_32];
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
switch (event) {
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
bfa_fcb_itnim_offline(itnim->itnim_drv);
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, bfa_log_level,
"Target (WWN = %s) connectivity lost for "
"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
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:
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_hcb_offline(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_HCB_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);
}
}
/*
* This state is set when a discovered rport is also in intiator mode.
* This ITN is marked as no_op and is not active and will not be truned into
* online state.
*/
static void
bfa_fcs_itnim_sm_initiator(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_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
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_INITIATOR:
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_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;
struct bfa_fcs_rport_s *rport = itnim->rport;
struct bfa_fcs_lport_s *port = rport->port;
struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
int len;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
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_TRUE);
return;
}
itnim->fcxp = fcxp;
len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
BFA_FALSE, FC_CLASS_3, len, &fchs,
bfa_fcs_itnim_prli_response, (void *)itnim,
FC_MAX_PDUSZ, FC_ELS_TOV);
itnim->stats.prli_sent++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
}
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)
{
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
struct fc_els_cmd_s *els_cmd;
struct fc_prli_s *prli_resp;
struct fc_ls_rjt_s *ls_rjt;
struct fc_prli_params_s *sparams;
bfa_trc(itnim->fcs, req_status);
/*
* Sanity Checks
*/
if (req_status != BFA_STATUS_OK) {
itnim->stats.prli_rsp_err++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
return;
}
els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
if (els_cmd->els_code == FC_ELS_ACC) {
prli_resp = (struct fc_prli_s *) els_cmd;
if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
bfa_trc(itnim->fcs, rsp_len);
/*
* Check if this r-port is also in Initiator mode.
* If so, we need to set this ITN as a no-op.
*/
if (prli_resp->parampage.servparams.initiator) {
bfa_trc(itnim->fcs, prli_resp->parampage.type);
itnim->rport->scsi_function =
BFA_RPORT_INITIATOR;
itnim->stats.prli_rsp_acc++;
itnim->stats.initiator++;
bfa_sm_send_event(itnim,
BFA_FCS_ITNIM_SM_RSP_OK);
return;
}
itnim->stats.prli_rsp_parse_err++;
return;
}
itnim->rport->scsi_function = BFA_RPORT_TARGET;
sparams = &prli_resp->parampage.servparams;
itnim->seq_rec = sparams->retry;
itnim->rec_support = sparams->rec_support;
itnim->task_retry_id = sparams->task_retry_id;
itnim->conf_comp = sparams->confirm;
itnim->stats.prli_rsp_acc++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
} else {
ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
bfa_trc(itnim->fcs, ls_rjt->reason_code);
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);
}
}
static void
bfa_fcs_itnim_timeout(void *arg)
{
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
itnim->stats.timeout++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
}
static void
bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *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);
}
/*
* itnim_public FCS ITNIM public interfaces
*/
/*
* Called by rport when a new rport is created.
*
* @param[in] rport - remote port.
*/
struct bfa_fcs_itnim_s *
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;
/*
* call bfad to allocate the itnim
*/
bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
if (itnim == NULL) {
bfa_trc(port->fcs, rport->pwwn);
return NULL;
}
/*
* Initialize itnim
*/
itnim->rport = rport;
itnim->fcs = rport->fcs;
itnim->itnim_drv = itnim_drv;
itnim->bfa_itnim = NULL;
itnim->seq_rec = BFA_FALSE;
itnim->rec_support = BFA_FALSE;
itnim->conf_comp = BFA_FALSE;
itnim->task_retry_id = BFA_FALSE;
/*
* Set State machine
*/
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
return itnim;
}
/*
* Called by rport to delete the instance of FCPIM.
*
* @param[in] rport - remote port.
*/
void
bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
{
bfa_trc(itnim->fcs, itnim->rport->pid);
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
}
/*
* Notification from rport that PLOGI is complete to initiate FC-4 session.
*/
void
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_HAL_ONLINE);
}
/*
* Called by rport to handle a remote device offline.
*/
void
bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
{
itnim->stats.offlines++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
}
/*
* Called by rport when remote port is known to be an initiator from
* PRLI received.
*/
void
bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
{
bfa_trc(itnim->fcs, itnim->rport->pid);
itnim->stats.initiator++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
}
/*
* Called by rport to check if the itnim is online.
*/
bfa_status_t
bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
{
bfa_trc(itnim->fcs, itnim->rport->pid);
switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
case BFA_ITNIM_ONLINE:
case BFA_ITNIM_INITIATIOR:
return BFA_STATUS_OK;
default:
return BFA_STATUS_NO_FCPIM_NEXUS;
}
}
/*
* BFA completion callback for bfa_itnim_online().
*/
void
bfa_cb_itnim_online(void *cbarg)
{
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
}
/*
* BFA completion callback for bfa_itnim_offline().
*/
void
bfa_cb_itnim_offline(void *cb_arg)
{
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
}
/*
* Mark the beginning of PATH TOV handling. IO completion callbacks
* are still pending.
*/
void
bfa_cb_itnim_tov_begin(void *cb_arg)
{
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
}
/*
* Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
*/
void
bfa_cb_itnim_tov(void *cb_arg)
{
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
itnim_drv->state = ITNIM_STATE_TIMEOUT;
}
/*
* 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.
*/
void
bfa_cb_itnim_sler(void *cb_arg)
{
struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
itnim->stats.sler++;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
}
struct bfa_fcs_itnim_s *
bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
{
struct bfa_fcs_rport_s *rport;
rport = bfa_fcs_rport_lookup(port, rpwwn);
if (!rport)
return NULL;
WARN_ON(rport->itnim == NULL);
return rport->itnim;
}
bfa_status_t
bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
struct bfa_itnim_attr_s *attr)
{
struct bfa_fcs_itnim_s *itnim = NULL;
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
if (itnim == NULL)
return BFA_STATUS_NO_FCPIM_NEXUS;
attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
attr->retry = itnim->seq_rec;
attr->rec_support = itnim->rec_support;
attr->conf_comp = itnim->conf_comp;
attr->task_retry_id = itnim->task_retry_id;
return BFA_STATUS_OK;
}
bfa_status_t
bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
struct bfa_itnim_stats_s *stats)
{
struct bfa_fcs_itnim_s *itnim = NULL;
WARN_ON(port == NULL);
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
if (itnim == NULL)
return BFA_STATUS_NO_FCPIM_NEXUS;
memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
return BFA_STATUS_OK;
}
bfa_status_t
bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
{
struct bfa_fcs_itnim_s *itnim = NULL;
WARN_ON(port == NULL);
itnim = bfa_fcs_itnim_lookup(port, rpwwn);
if (itnim == NULL)
return BFA_STATUS_NO_FCPIM_NEXUS;
memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
return BFA_STATUS_OK;
}
void
bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
struct fchs_s *fchs, u16 len)
{
struct fc_els_cmd_s *els_cmd;
bfa_trc(itnim->fcs, fchs->type);
if (fchs->type != FC_TYPE_ELS)
return;
els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
bfa_trc(itnim->fcs, els_cmd->els_code);
switch (els_cmd->els_code) {
case FC_ELS_PRLO:
bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);
break;
default:
WARN_ON(1);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,191 @@
/*
* 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 "bfad_drv.h"
#include "bfa_modules.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 fn = bfa_ioc_pcifn(&bfa->ioc);
if (fn == 0) {
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK);
} else {
bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
}
}
static void
bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
{
writel(__HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq),
bfa->iocfc.bfa_regs.intr_status);
}
/*
* 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();
}
void
bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
{
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
bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
u32 *num_vecs, u32 *max_vec_bit)
{
#define __HFN_NUMINTS 13
if (bfa_ioc_pcifn(&bfa->ioc) == 0) {
*msix_vecs_bmap = (__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);
*max_vec_bit = __HFN_INT_MBOX_LPU0;
} else {
*msix_vecs_bmap = (__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);
*max_vec_bit = __HFN_INT_MBOX_LPU1;
}
*msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
*num_vecs = __HFN_NUMINTS;
}
/*
* 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;
if (bfa->msix.nvecs == 0)
return;
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 = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
bfa->msix.handler[i] = bfa_msix_lpu_err;
}
void
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;
}
/*
* No special enable/disable -- vector assignments are implicit.
*/
void
bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t 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 = BFI_MSIX_RME_QMIN_CB;
*end = BFI_MSIX_RME_QMAX_CB;
}

View file

@ -0,0 +1,178 @@
/*
* 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 "bfad_drv.h"
#include "bfa_modules.h"
#include "bfi_reg.h"
BFA_TRC_FILE(HAL, IOCFC_CT);
/*
* Dummy interrupt handler for handling spurious interrupt during chip-reinit.
*/
static void
bfa_hwct_msix_dummy(struct bfa_s *bfa, int vec)
{
}
void
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 fn = bfa_ioc_pcifn(&bfa->ioc);
if (fn == 0) {
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK);
} else {
bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK);
}
}
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
bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq)
{
u32 r32;
r32 = readl(bfa->iocfc.bfa_regs.cpe_q_ctrl[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, 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 << BFI_MSIX_CT_MAX) - 1;
*max_vec_bit = (1 << (BFI_MSIX_CT_MAX - 1));
*num_vecs = BFI_MSIX_CT_MAX;
}
/*
* Setup MSI-X vector for catapult
*/
void
bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
{
WARN_ON((nvecs != 1) && (nvecs != BFI_MSIX_CT_MAX));
bfa_trc(bfa, nvecs);
bfa->msix.nvecs = nvecs;
bfa_hwct_msix_uninstall(bfa);
}
void
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;
if (bfa->msix.nvecs == 0)
return;
if (bfa->msix.nvecs == 1) {
for (i = BFI_MSIX_CPE_QMIN_CT; i < BFI_MSIX_CT_MAX; i++)
bfa->msix.handler[i] = bfa_msix_all;
return;
}
for (i = BFI_MSIX_CPE_QMIN_CT; i <= BFI_MSIX_CPE_QMAX_CT; i++)
bfa->msix.handler[i] = bfa_msix_reqq;
for (i = BFI_MSIX_RME_QMIN_CT; i <= BFI_MSIX_RME_QMAX_CT; i++)
bfa->msix.handler[i] = bfa_msix_rspq;
}
void
bfa_hwct_msix_uninstall(struct bfa_s *bfa)
{
int i;
for (i = 0; i < BFI_MSIX_CT_MAX; i++)
bfa->msix.handler[i] = bfa_hwct_msix_dummy;
}
/*
* Enable MSI-X vectors
*/
void
bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
{
bfa_trc(bfa, 0);
bfa_ioc_isr_mode_set(&bfa->ioc, msix);
}
void
bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
{
*start = BFI_MSIX_RME_QMIN_CT;
*end = BFI_MSIX_RME_QMAX_CT;
}

7065
drivers/scsi/bfa/bfa_ioc.c Normal file

File diff suppressed because it is too large Load diff

1048
drivers/scsi/bfa/bfa_ioc.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,408 @@
/*
* 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 "bfad_drv.h"
#include "bfa_ioc.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
*/
static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc);
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_fail(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc);
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.
*/
void
bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
{
hwif_cb.ioc_pll_init = bfa_ioc_cb_pll_init;
hwif_cb.ioc_firmware_lock = bfa_ioc_cb_firmware_lock;
hwif_cb.ioc_firmware_unlock = bfa_ioc_cb_firmware_unlock;
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_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;
}
/*
* Return true if firmware of current driver matches the running firmware.
*/
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;
}
static void
bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)
{
}
/*
* Notify other functions on HB failure.
*/
static void
bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)
{
writel(~0U, ioc->ioc_regs.err_set);
readl(ioc->ioc_regs.err_set);
}
/*
* Host to LPU mailbox message addresses
*/
static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_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 }
};
/*
* Host <-> LPU mailbox command/status registers
*/
static struct { u32 hfn, lpu; } iocreg_mbcmd[] = {
{ HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
{ HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }
};
static void
bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
{
void __iomem *rb;
int pcifn = bfa_ioc_pcifn(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;
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);
}
/*
* Host <-> LPU mailbox command/status registers
*/
ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd[pcifn].hfn;
ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd[pcifn].lpu;
/*
* 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 + APP_PLL_LCLK_CTL_REG);
ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
/*
* IOC semaphore registers and serialization
*/
ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
/*
* sram memory access
*/
ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB;
/*
* err set reg : for notification of hb failure
*/
ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
}
/*
* Initialize IOC to port mapping.
*/
static void
bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
{
/*
* For crossbow, port id is same as pci function.
*/
ioc->port_id = bfa_ioc_pcifn(ioc);
bfa_trc(ioc, ioc->port_id);
}
/*
* Set interrupt mode for a function: INTX or MSIX
*/
static void
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
bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
{
/*
* 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);
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, 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_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_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_SCLK_CTL_REG));
writel(pll_fclk, (rb + APP_PLL_LCLK_CTL_REG));
return BFA_STATUS_OK;
}

View file

@ -0,0 +1,997 @@
/*
* 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 "bfad_drv.h"
#include "bfa_ioc.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_notify_fail(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc);
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.
*/
static bfa_boolean_t
bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
{
enum bfi_ioc_state ioc_fwstate;
u32 usecnt;
struct bfi_ioc_image_hdr_s fwhdr;
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
/*
* If usage count is 0, always return TRUE.
*/
if (usecnt == 0) {
writel(1, 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);
bfa_trc(ioc, usecnt);
return BFA_TRUE;
}
ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
bfa_trc(ioc, ioc_fwstate);
/*
* Use count cannot be non-zero and chip in uninitialized state.
*/
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)) {
readl(ioc->ioc_regs.ioc_usage_sem_reg);
writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
bfa_trc(ioc, usecnt);
return BFA_FALSE;
}
/*
* Same firmware version. Increment the reference count.
*/
usecnt++;
writel(usecnt, ioc->ioc_regs.ioc_usage_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;
}
static void
bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
{
u32 usecnt;
/*
* decrement usage count
*/
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
WARN_ON(usecnt <= 0);
usecnt--;
writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
bfa_trc(ioc, usecnt);
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_fail(struct bfa_ioc_s *ioc)
{
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(~0U, ioc->ioc_regs.err_set);
readl(ioc->ioc_regs.err_set);
}
}
/*
* Host to LPU mailbox message addresses
*/
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 },
{ HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
};
/*
* Host <-> LPU mailbox command/status registers - port 0
*/
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; } 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
bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
{
void __iomem *rb;
int pcifn = bfa_ioc_pcifn(ioc);
rb = bfa_ioc_bar0(ioc);
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.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.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;
}
/*
* 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 + APP_PLL_LCLK_CTL_REG);
ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
/*
* IOC semaphore registers and serialization
*/
ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
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
*/
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);
}
/*
* Initialize IOC to port mapping.
*/
#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8)
static void
bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc)
{
void __iomem *rb = ioc->pcidev.pci_bar_kva;
u32 r32;
/*
* For catapult, base port id on personality register and IOC type
*/
r32 = readl(rb + FNC_PERS_REG);
r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
bfa_trc(ioc, bfa_ioc_pcifn(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
*/
static void
bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
{
void __iomem *rb = ioc->pcidev.pci_bar_kva;
u32 r32, mode;
r32 = readl(rb + FNC_PERS_REG);
bfa_trc(ioc, r32);
mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
__F0_INTX_STATUS;
/*
* If already in desired mode, do not change anything
*/
if ((!msix && mode) || (msix && !mode))
return;
if (msix)
mode = __F0_INTX_STATUS_MSIX;
else
mode = __F0_INTX_STATUS_INTA;
r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
bfa_trc(ioc, r32);
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
*/
static void
bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
{
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);
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);
}
/*
* Synchronized IOC failure processing routines
*/
static void
bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc)
{
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, 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);
if (fcmode) {
writel(0, (rb + OP_MODE));
writel(__APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 |
__APP_EMS_CHANNEL_SEL, (rb + ETH_MAC_SER_REG));
} else {
writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
writel(__APP_EMS_REFCKBUFEN1, (rb + ETH_MAC_SER_REG));
}
writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
writel(BFI_IOC_UNINIT, (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(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_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));
}
r32 = readl((rb + PSS_CTL_REG));
r32 &= ~__PSS_LMEM_RESET;
writel(r32, (rb + PSS_CTL_REG));
udelay(1000);
if (!fcmode) {
writel(0, (rb + PMM_1T_RESET_REG_P0));
writel(0, (rb + PMM_1T_RESET_REG_P1));
}
writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
udelay(1000);
r32 = readl((rb + MBIST_STAT_REG));
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);
}

View file

@ -0,0 +1,139 @@
/*
* 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.
*/
/*
* bfa_modules.h BFA modules
*/
#ifndef __BFA_MODULES_H__
#define __BFA_MODULES_H__
#include "bfa_cs.h"
#include "bfa.h"
#include "bfa_svc.h"
#include "bfa_fcpim.h"
#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_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 */
};
/*
* !!! Only append to the enums defined here to avoid any versioning
* !!! needed between trace utility and driver version
*/
enum {
BFA_TRC_HAL_CORE = 1,
BFA_TRC_HAL_FCXP = 2,
BFA_TRC_HAL_FCPIM = 3,
BFA_TRC_HAL_IOCFC_CT = 4,
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, \
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_pcidev_s *pcidev); \
static void bfa_ ## __mod ## _detach(struct bfa_s *bfa); \
static void bfa_ ## __mod ## _start(struct bfa_s *bfa); \
static void bfa_ ## __mod ## _stop(struct bfa_s *bfa); \
static void bfa_ ## __mod ## _iocdisable(struct bfa_s *bfa); \
\
extern struct bfa_module_s hal_mod_ ## __mod; \
struct bfa_module_s hal_mod_ ## __mod = { \
bfa_ ## __mod ## _meminfo, \
bfa_ ## __mod ## _attach, \
bfa_ ## __mod ## _detach, \
bfa_ ## __mod ## _start, \
bfa_ ## __mod ## _stop, \
bfa_ ## __mod ## _iocdisable, \
}
#define BFA_CACHELINE_SZ (256)
/*
* Structure used to interact between different BFA sub modules
*
* Each sub module needs to implement only the entry points relevant to it (and
* can leave entry points as NULL)
*/
struct bfa_module_s {
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_pcidev_s *pcidev);
void (*detach) (struct bfa_s *bfa);
void (*start) (struct bfa_s *bfa);
void (*stop) (struct bfa_s *bfa);
void (*iocdisable) (struct bfa_s *bfa);
};
struct bfa_s {
void *bfad; /* BFA driver instance */
struct bfa_plog_s *plog; /* portlog buffer */
struct bfa_trc_mod_s *trcmod; /* driver tracing */
struct bfa_ioc_s ioc; /* IOC module */
struct bfa_iocfc_s iocfc; /* IOCFC module */
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 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_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_fcp;
extern struct bfa_module_s hal_mod_dconf;
#endif /* __BFA_MODULES_H__ */

155
drivers/scsi/bfa/bfa_plog.h Normal file
View file

@ -0,0 +1,155 @@
/*
* 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_PORTLOG_H__
#define __BFA_PORTLOG_H__
#include "bfa_fc.h"
#include "bfa_defs.h"
#define BFA_PL_NLOG_ENTS 256
#define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS)
#define BFA_PL_STRING_LOG_SZ 32 /* number of chars in string log */
#define BFA_PL_INT_LOG_SZ 8 /* number of integers in the integer log */
enum bfa_plog_log_type {
BFA_PL_LOG_TYPE_INVALID = 0,
BFA_PL_LOG_TYPE_INT = 1,
BFA_PL_LOG_TYPE_STRING = 2,
};
/*
* the (fixed size) record format for each entry in the portlog
*/
struct bfa_plog_rec_s {
u64 tv; /* timestamp */
u8 port; /* Source port that logged this entry */
u8 mid; /* module id */
u8 eid; /* indicates Rx, Tx, IOCTL, etc. bfa_plog_eid */
u8 log_type; /* string/integer log, bfa_plog_log_type_t */
u8 log_num_ints;
/*
* interpreted only if log_type is INT_LOG. indicates number of
* integers in the int_log[] (0-PL_INT_LOG_SZ).
*/
u8 rsvd;
u16 misc; /* can be used to indicate fc frame length */
union {
char string_log[BFA_PL_STRING_LOG_SZ];
u32 int_log[BFA_PL_INT_LOG_SZ];
} log_entry;
};
/*
* the following #defines will be used by the logging entities to indicate
* their module id. BFAL will convert the integer value to string format
*
* process to be used while changing the following #defines:
* - Always add new entries at the end
* - define corresponding string in BFAL
* - Do not remove any entry or rearrange the order.
*/
enum bfa_plog_mid {
BFA_PL_MID_INVALID = 0,
BFA_PL_MID_DEBUG = 1,
BFA_PL_MID_DRVR = 2,
BFA_PL_MID_HAL = 3,
BFA_PL_MID_HAL_FCXP = 4,
BFA_PL_MID_HAL_UF = 5,
BFA_PL_MID_FCS = 6,
BFA_PL_MID_LPS = 7,
BFA_PL_MID_MAX = 8
};
#define BFA_PL_MID_STRLEN 8
struct bfa_plog_mid_strings_s {
char m_str[BFA_PL_MID_STRLEN];
};
/*
* the following #defines will be used by the logging entities to indicate
* their event type. BFAL will convert the integer value to string format
*
* process to be used while changing the following #defines:
* - Always add new entries at the end
* - define corresponding string in BFAL
* - Do not remove any entry or rearrange the order.
*/
enum bfa_plog_eid {
BFA_PL_EID_INVALID = 0,
BFA_PL_EID_IOC_DISABLE = 1,
BFA_PL_EID_IOC_ENABLE = 2,
BFA_PL_EID_PORT_DISABLE = 3,
BFA_PL_EID_PORT_ENABLE = 4,
BFA_PL_EID_PORT_ST_CHANGE = 5,
BFA_PL_EID_TX = 6,
BFA_PL_EID_TX_ACK1 = 7,
BFA_PL_EID_TX_RJT = 8,
BFA_PL_EID_TX_BSY = 9,
BFA_PL_EID_RX = 10,
BFA_PL_EID_RX_ACK1 = 11,
BFA_PL_EID_RX_RJT = 12,
BFA_PL_EID_RX_BSY = 13,
BFA_PL_EID_CT_IN = 14,
BFA_PL_EID_CT_OUT = 15,
BFA_PL_EID_DRIVER_START = 16,
BFA_PL_EID_RSCN = 17,
BFA_PL_EID_DEBUG = 18,
BFA_PL_EID_MISC = 19,
BFA_PL_EID_FIP_FCF_DISC = 20,
BFA_PL_EID_FIP_FCF_CVL = 21,
BFA_PL_EID_LOGIN = 22,
BFA_PL_EID_LOGO = 23,
BFA_PL_EID_TRUNK_SCN = 24,
BFA_PL_EID_MAX
};
#define BFA_PL_ENAME_STRLEN 8
struct bfa_plog_eid_strings_s {
char e_str[BFA_PL_ENAME_STRLEN];
};
#define BFA_PL_SIG_LEN 8
#define BFA_PL_SIG_STR "12pl123"
/*
* per port circular log buffer
*/
struct bfa_plog_s {
char plog_sig[BFA_PL_SIG_LEN]; /* Start signature */
u8 plog_enabled;
u8 rsvd[7];
u32 ticks;
u16 head;
u16 tail;
struct bfa_plog_rec_s plog_recs[BFA_PL_NLOG_ENTS];
};
void bfa_plog_init(struct bfa_plog_s *plog);
void bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
enum bfa_plog_eid event, u16 misc, char *log_str);
void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
enum bfa_plog_eid event, u16 misc,
u32 *intarr, u32 num_ints);
void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr);
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);
#endif /* __BFA_PORTLOG_H__ */

880
drivers/scsi/bfa/bfa_port.c Normal file
View file

@ -0,0 +1,880 @@
/*
* 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 "bfad_drv.h"
#include "bfa_defs_svc.h"
#include "bfa_port.h"
#include "bfi.h"
#include "bfa_ioc.h"
BFA_TRC_FILE(CNA, PORT);
static void
bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
{
u32 *dip = (u32 *) stats;
__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 __BIG_ENDIAN
dip[i] = be32_to_cpu(t0);
dip[i + 1] = be32_to_cpu(t1);
#else
dip[i] = be32_to_cpu(t1);
dip[i + 1] = be32_to_cpu(t0);
#endif
}
}
/*
* bfa_port_enable_isr()
*
*
* @param[in] port - Pointer to the port module
* status - Return status from the f/w
*
* @return void
*/
static void
bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
{
bfa_trc(port, status);
port->endis_pending = BFA_FALSE;
port->endis_cbfn(port->endis_cbarg, status);
}
/*
* bfa_port_disable_isr()
*
*
* @param[in] port - Pointer to the port module
* status - Return status from the f/w
*
* @return void
*/
static void
bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status)
{
bfa_trc(port, status);
port->endis_pending = BFA_FALSE;
port->endis_cbfn(port->endis_cbarg, status);
}
/*
* bfa_port_get_stats_isr()
*
*
* @param[in] port - Pointer to the Port module
* status - Return status from the f/w
*
* @return void
*/
static void
bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status)
{
port->stats_status = status;
port->stats_busy = BFA_FALSE;
if (status == BFA_STATUS_OK) {
struct timeval tv;
memcpy(port->stats, port->stats_dma.kva,
sizeof(union bfa_port_stats_u));
bfa_port_stats_swap(port, port->stats);
do_gettimeofday(&tv);
port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time;
}
if (port->stats_cbfn) {
port->stats_cbfn(port->stats_cbarg, status);
port->stats_cbfn = NULL;
}
}
/*
* bfa_port_clear_stats_isr()
*
*
* @param[in] port - Pointer to the Port module
* status - Return status from the f/w
*
* @return void
*/
static void
bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
{
struct timeval tv;
port->stats_status = status;
port->stats_busy = BFA_FALSE;
/*
* re-initialize time stamp for stats reset
*/
do_gettimeofday(&tv);
port->stats_reset_time = tv.tv_sec;
if (port->stats_cbfn) {
port->stats_cbfn(port->stats_cbarg, status);
port->stats_cbfn = NULL;
}
}
/*
* bfa_port_isr()
*
*
* @param[in] Pointer to the Port module data structure.
*
* @return void
*/
static void
bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
{
struct bfa_port_s *port = (struct bfa_port_s *) cbarg;
union bfi_port_i2h_msg_u *i2hmsg;
i2hmsg = (union bfi_port_i2h_msg_u *) m;
bfa_trc(port, m->mh.msg_id);
switch (m->mh.msg_id) {
case BFI_PORT_I2H_ENABLE_RSP:
if (port->endis_pending == BFA_FALSE)
break;
bfa_port_enable_isr(port, i2hmsg->enable_rsp.status);
break;
case BFI_PORT_I2H_DISABLE_RSP:
if (port->endis_pending == BFA_FALSE)
break;
bfa_port_disable_isr(port, i2hmsg->disable_rsp.status);
break;
case BFI_PORT_I2H_GET_STATS_RSP:
/* Stats busy flag is still set? (may be cmd timed out) */
if (port->stats_busy == BFA_FALSE)
break;
bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status);
break;
case BFI_PORT_I2H_CLEAR_STATS_RSP:
if (port->stats_busy == BFA_FALSE)
break;
bfa_port_clear_stats_isr(port, i2hmsg->clearstats_rsp.status);
break;
default:
WARN_ON(1);
}
}
/*
* bfa_port_meminfo()
*
*
* @param[in] void
*
* @return Size of DMA region
*/
u32
bfa_port_meminfo(void)
{
return BFA_ROUNDUP(sizeof(union bfa_port_stats_u), BFA_DMA_ALIGN_SZ);
}
/*
* bfa_port_mem_claim()
*
*
* @param[in] port Port module pointer
* dma_kva Kernel Virtual Address of Port DMA Memory
* dma_pa Physical Address of Port DMA Memory
*
* @return void
*/
void
bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
{
port->stats_dma.kva = dma_kva;
port->stats_dma.pa = dma_pa;
}
/*
* bfa_port_enable()
*
* Send the Port enable request to the f/w
*
* @param[in] Pointer to the Port module data structure.
*
* @return Status
*/
bfa_status_t
bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
void *cbarg)
{
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;
}
if (!bfa_ioc_is_operational(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
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;
}
m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
port->msgtag++;
port->endis_cbfn = cbfn;
port->endis_cbarg = cbarg;
port->endis_pending = BFA_TRUE;
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ,
bfa_ioc_portid(port->ioc));
bfa_ioc_mbox_queue(port->ioc, &port->endis_mb);
return BFA_STATUS_OK;
}
/*
* bfa_port_disable()
*
* Send the Port disable request to the f/w
*
* @param[in] Pointer to the Port module data structure.
*
* @return Status
*/
bfa_status_t
bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
void *cbarg)
{
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;
}
if (!bfa_ioc_is_operational(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
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;
}
m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
port->msgtag++;
port->endis_cbfn = cbfn;
port->endis_cbarg = cbarg;
port->endis_pending = BFA_TRUE;
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ,
bfa_ioc_portid(port->ioc));
bfa_ioc_mbox_queue(port->ioc, &port->endis_mb);
return BFA_STATUS_OK;
}
/*
* bfa_port_get_stats()
*
* Send the request to the f/w to fetch Port statistics.
*
* @param[in] Pointer to the Port module data structure.
*
* @return Status
*/
bfa_status_t
bfa_port_get_stats(struct bfa_port_s *port, union bfa_port_stats_u *stats,
bfa_port_stats_cbfn_t cbfn, void *cbarg)
{
struct bfi_port_get_stats_req_s *m;
if (!bfa_ioc_is_operational(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
return BFA_STATUS_IOC_FAILURE;
}
if (port->stats_busy) {
bfa_trc(port, BFA_STATUS_DEVBUSY);
return BFA_STATUS_DEVBUSY;
}
m = (struct bfi_port_get_stats_req_s *) port->stats_mb.msg;
port->stats = stats;
port->stats_cbfn = cbfn;
port->stats_cbarg = cbarg;
port->stats_busy = BFA_TRUE;
bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa);
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ,
bfa_ioc_portid(port->ioc));
bfa_ioc_mbox_queue(port->ioc, &port->stats_mb);
return BFA_STATUS_OK;
}
/*
* bfa_port_clear_stats()
*
*
* @param[in] Pointer to the Port module data structure.
*
* @return Status
*/
bfa_status_t
bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
void *cbarg)
{
struct bfi_port_generic_req_s *m;
if (!bfa_ioc_is_operational(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
return BFA_STATUS_IOC_FAILURE;
}
if (port->stats_busy) {
bfa_trc(port, BFA_STATUS_DEVBUSY);
return BFA_STATUS_DEVBUSY;
}
m = (struct bfi_port_generic_req_s *) port->stats_mb.msg;
port->stats_cbfn = cbfn;
port->stats_cbarg = cbarg;
port->stats_busy = BFA_TRUE;
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ,
bfa_ioc_portid(port->ioc));
bfa_ioc_mbox_queue(port->ioc, &port->stats_mb);
return BFA_STATUS_OK;
}
/*
* 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_notify(void *arg, enum bfa_ioc_event_e event)
{
struct bfa_port_s *port = (struct bfa_port_s *) arg;
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;
}
}
/*
* bfa_port_attach()
*
*
* @param[in] port - Pointer to the Port 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.
* trcmod -
*
* @return void
*/
void
bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
void *dev, struct bfa_trc_mod_s *trcmod)
{
struct timeval tv;
WARN_ON(!port);
port->dev = dev;
port->ioc = ioc;
port->trcmod = trcmod;
port->stats_busy = BFA_FALSE;
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_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
*/
do_gettimeofday(&tv);
port->stats_reset_time = tv.tv_sec;
bfa_trc(port, 0);
}
/*
* 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_set_dportenabled(struct bfa_port_s *port, bfa_boolean_t enabled)
{
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);
}

126
drivers/scsi/bfa/bfa_port.h Normal file
View file

@ -0,0 +1,126 @@
/*
* 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_PORT_H__
#define __BFA_PORT_H__
#include "bfa_defs_svc.h"
#include "bfa_ioc.h"
#include "bfa_cs.h"
typedef void (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
typedef void (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
struct bfa_port_s {
void *dev;
struct bfa_ioc_s *ioc;
struct bfa_trc_mod_s *trcmod;
u32 msgtag;
bfa_boolean_t stats_busy;
struct bfa_mbox_cmd_s stats_mb;
bfa_port_stats_cbfn_t stats_cbfn;
void *stats_cbarg;
bfa_status_t stats_status;
u32 stats_reset_time;
union bfa_port_stats_u *stats;
struct bfa_dma_s stats_dma;
bfa_boolean_t endis_pending;
struct bfa_mbox_cmd_s endis_mb;
bfa_port_endis_cbfn_t endis_cbfn;
void *endis_cbarg;
bfa_status_t endis_status;
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_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,
bfa_port_stats_cbfn_t cbfn, void *cbarg);
bfa_status_t bfa_port_clear_stats(struct bfa_port_s *port,
bfa_port_stats_cbfn_t cbfn, void *cbarg);
bfa_status_t bfa_port_enable(struct bfa_port_s *port,
bfa_port_endis_cbfn_t cbfn, void *cbarg);
bfa_status_t bfa_port_disable(struct bfa_port_s *port,
bfa_port_endis_cbfn_t cbfn, void *cbarg);
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__ */

7062
drivers/scsi/bfa/bfa_svc.c Normal file

File diff suppressed because it is too large Load diff

763
drivers/scsi/bfa/bfa_svc.h Normal file
View file

@ -0,0 +1,763 @@
/*
* 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_SVC_H__
#define __BFA_SVC_H__
#include "bfa_cs.h"
#include "bfi_ms.h"
/*
* Scatter-gather DMA related defines
*/
#define BFA_SGPG_MIN (16)
#define BFA_SGPG_MAX (8192)
/*
* Alignment macro for SG page allocation
*/
#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \
& ~(sizeof(struct bfi_sgpg_s) - 1))
struct bfa_sgpg_wqe_s {
struct list_head qe; /* queue sg page element */
int nsgpg; /* pages to be allocated */
int nsgpg_total; /* total pages required */
void (*cbfn) (void *cbarg); /* callback function */
void *cbarg; /* callback arg */
struct list_head sgpg_q; /* queue of alloced sgpgs */
};
struct bfa_sgpg_s {
struct list_head qe; /* queue sg page element */
struct bfi_sgpg_s *sgpg; /* va of SG page */
union bfi_addr_u sgpg_pa; /* pa of SG page */
};
/*
* Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
* SG pages required.
*/
#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 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);
void bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs);
void bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
void (*cbfn) (void *cbarg), void *cbarg);
void bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpgs);
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_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,
u32 rsp_len, u32 resid_len,
struct fchs_s *rsp_fchs);
typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
void *cbarg, enum bfa_status req_status,
u32 rsp_len, u32 resid_len,
struct fchs_s *rsp_fchs);
typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
/*
* Information needed for a FCXP request
*/
struct bfa_fcxp_req_info_s {
struct bfa_rport_s *bfa_rport;
/* Pointer to the bfa rport that was
* returned from bfa_rport_create().
* This could be left NULL for WKA or
* for FCXP interactions before the
* rport nexus is established
*/
struct fchs_s fchs; /* request FC header structure */
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 */
u8 lp_tag; /* lport tag */
u32 req_tot_len; /* request payload total length */
};
struct bfa_fcxp_rsp_info_s {
struct fchs_s rsp_fchs;
/* Response frame's FC header will
* be sent back in this field */
u8 rsp_timeout;
/* timeout in seconds, 0-no response */
u8 rsvd2[3];
u32 rsp_maxlen; /* max response length expected */
};
struct bfa_fcxp_s {
struct list_head qe; /* fcxp queue element */
bfa_sm_t sm; /* state machine */
void *caller; /* driver or fcs */
struct bfa_fcxp_mod_s *fcxp_mod;
/* back pointer to fcxp mod */
u16 fcxp_tag; /* internal tag */
struct bfa_fcxp_req_info_s req_info;
/* request info */
struct bfa_fcxp_rsp_info_s rsp_info;
/* response info */
u8 use_ireqbuf; /* use internal req buf */
u8 use_irspbuf; /* use internal rsp buf */
u32 nreq_sgles; /* num request SGLEs */
u32 nrsp_sgles; /* num response SGLEs */
struct list_head req_sgpg_q; /* SG pages for request buf */
struct list_head req_sgpg_wqe; /* wait queue for req SG page */
struct list_head rsp_sgpg_q; /* SG pages for response buf */
struct list_head rsp_sgpg_wqe; /* wait queue for rsp SG page */
bfa_fcxp_get_sgaddr_t req_sga_cbfn;
/* SG elem addr user function */
bfa_fcxp_get_sglen_t req_sglen_cbfn;
/* SG elem len user function */
bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
/* SG elem addr user function */
bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
/* SG elem len user function */
bfa_cb_fcxp_send_t send_cbfn; /* send completion callback */
void *send_cbarg; /* callback arg */
struct bfa_sge_s req_sge[BFA_FCXP_MAX_SGES];
/* req SG elems */
struct bfa_sge_s rsp_sge[BFA_FCXP_MAX_SGES];
/* rsp SG elems */
u8 rsp_status; /* comp: rsp status */
u32 rsp_len; /* comp: actual response len */
u32 residue_len; /* comp: residual rsp length */
struct fchs_s rsp_fchs; /* comp: response fchs */
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 {
struct list_head qe;
bfa_fcxp_alloc_cbfn_t alloc_cbfn;
void *alloc_cbarg;
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;
};
#define BFA_FCXP_REQ_PLD(_fcxp) (bfa_fcxp_get_reqbuf(_fcxp))
#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) \
bfa_mem_get_dmabuf_pa((_fcxp)->fcxp_mod, (_fcxp)->fcxp_tag, \
(_fcxp)->fcxp_mod->req_pld_sz + (_fcxp)->fcxp_mod->rsp_pld_sz)
/* 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);
/*
* 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
*/
#define BFA_RPORT_FROM_TAG(__bfa, _tag) \
(BFA_RPORT_MOD(__bfa)->rps_list + \
((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
/*
* 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.
*/
struct bfa_rport_info_s {
u16 max_frmsz; /* max rcv pdu size */
u32 pid:24, /* remote port ID */
lp_tag:8; /* tag */
u32 local_pid:24, /* local port ID */
cisc:8; /* CIRO supported */
u8 fc_class; /* supported FC classes. enum fc_cos */
u8 vf_en; /* virtual fabric enable */
u16 vf_id; /* virtual fabric ID */
enum bfa_port_speed speed; /* Rport's current speed */
};
/*
* BFA rport data structure
*/
struct bfa_rport_s {
struct list_head qe; /* queue element */
bfa_sm_t sm; /* state machine */
struct bfa_s *bfa; /* backpointer to BFA */
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 */
struct bfa_rport_hal_stats_s stats; /* BFA rport statistics */
struct bfa_rport_qos_attr_s qos_attr;
union a {
bfa_status_t status; /* f/w status */
void *fw_msg; /* QoS scn event */
} event_arg;
};
#define BFA_RPORT_FC_COS(_rport) ((_rport)->rport_info.fc_class)
/*
* UF - unsolicited receive related defines
*/
#define BFA_UF_MIN (4)
#define BFA_UF_MAX (256)
struct bfa_uf_s {
struct list_head qe; /* queue element */
struct bfa_s *bfa; /* bfa instance */
u16 uf_tag; /* identifying tag fw msgs */
u16 vf_id;
u16 src_rport_handle;
u16 rsvd;
u8 *data_ptr;
u16 data_len; /* actual receive length */
u16 pb_len; /* posted buffer length */
void *buf_kva; /* buffer virtual address */
u64 buf_pa; /* buffer physical address */
struct bfa_cb_qe_s hcb_qe; /* comp: BFA comp qelem */
struct bfa_sge_s sges[BFI_SGE_INLINE_MAX];
};
/*
* Callback prototype for unsolicited frame receive handler.
*
* @param[in] cbarg callback arg for receive handler
* @param[in] uf unsolicited frame descriptor
*
* @return None
*/
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 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) \
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);
void bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw);
/*
* LPS - bfa lport login/logout service interface
*/
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 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 */
bfa_boolean_t fdisc; /* snd FDISC instead of FLOGI */
bfa_boolean_t auth_en; /* enable authentication */
bfa_boolean_t auth_req; /* authentication required */
bfa_boolean_t npiv_en; /* NPIV is allowed by peer */
bfa_boolean_t fport; /* attached peer is F_PORT */
bfa_boolean_t brcd_switch; /* attached peer is brcd sw */
bfa_status_t status; /* login status */
u16 pdusz; /* max receive PDU size */
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 */
wwn_t pr_nwwn; /* node wwn of lport peer */
mac_t lp_mac; /* fpma/spma MAC for lport */
mac_t fcf_mac; /* FCF MAC of lport */
struct bfa_reqq_wait_s wqe; /* request wait queue element */
void *uarg; /* user callback arg */
struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
struct bfi_lps_login_rsp_s *loginrsp;
bfa_eproto_status_t ext_status;
};
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
*/
void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
/*
* FCPORT related defines
*/
#define BFA_FCPORT(_bfa) (&((_bfa)->modules.port))
/*
* Link notification data structure
*/
struct bfa_fcport_ln_s {
struct bfa_fcport_s *fcport;
bfa_sm_t sm;
struct bfa_cb_qe_s ln_qe; /* BFA callback queue elem for ln */
enum bfa_port_linkstate ln_event; /* ln event for callback */
};
struct bfa_fcport_trunk_s {
struct bfa_trunk_attr_s attr;
};
/*
* BFA FC port data structure
*/
struct bfa_fcport_s {
struct bfa_s *bfa; /* parent BFA instance */
bfa_sm_t sm; /* port state machine */
wwn_t nwwn; /* node wwn of physical port */
wwn_t pwwn; /* port wwn of physical oprt */
enum bfa_port_speed speed_sup;
/* supported speeds */
enum bfa_port_speed speed; /* current speed */
enum bfa_port_topology topology; /* current 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;
/* to wait for room in reqq */
struct bfa_reqq_wait_s svcreq_wait;
/* to wait for room in reqq */
struct bfa_reqq_wait_s stats_reqq_wait;
/* to wait for room in reqq (stats) */
void *event_cbarg;
void (*event_cbfn) (void *cbarg,
enum bfa_port_linkstate event);
union {
union bfi_fcport_i2h_msg_u i2hmsg;
} event_arg;
void *bfad; /* BFA driver handle */
struct bfa_fcport_ln_s ln; /* Link Notification */
struct bfa_cb_qe_s hcb_qe; /* BFA callback queue elem */
struct bfa_timer_s timer; /* timer */
u32 msgtag; /* fimrware msg tag for reply */
u8 *stats_kva;
u64 stats_pa;
union bfa_fcport_stats_u *stats;
bfa_status_t stats_status; /* stats/statsclr status */
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_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
*/
void bfa_fcport_init(struct bfa_s *bfa);
void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
/*
* bfa fcport API functions
*/
bfa_status_t bfa_fcport_enable(struct bfa_s *bfa);
bfa_status_t bfa_fcport_disable(struct bfa_s *bfa);
bfa_status_t bfa_fcport_cfg_speed(struct bfa_s *bfa,
enum bfa_port_speed speed);
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);
bfa_status_t bfa_fcport_clr_hardalpa(struct bfa_s *bfa);
bfa_status_t bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
u16 bfa_fcport_get_maxfrsize(struct bfa_s *bfa);
u8 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa);
void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr);
wwn_t bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
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);
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);
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,
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_online(struct bfa_rport_s *rport,
struct bfa_rport_info_s *rport_info);
void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed);
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);
/*
* 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_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,
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_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);
void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
u16 vf_id, u8 lp_tag,
bfa_boolean_t cts, enum fc_cos cos,
u32 reqlen, struct fchs_s *fchs,
bfa_cb_fcxp_send_t cbfn,
void *cbarg,
u32 rsp_maxlen, u8 rsp_timeout);
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)
{
return uf->data_ptr;
}
static inline u16
bfa_uf_get_frmlen(struct bfa_uf_s *uf)
{
return uf->data_len;
}
/*
* bfa uf API functions
*/
void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
void *cbarg);
void bfa_uf_free(struct bfa_uf_s *uf);
/*
* bfa lport service api
*/
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_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_fdisclogo(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);
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);
/* 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__ */

1826
drivers/scsi/bfa/bfad.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,999 @@
/*
* 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.
*/
/*
* bfa_attr.c Linux driver configuration interface module.
*/
#include "bfad_drv.h"
#include "bfad_im.h"
/*
* FC transport template entry, get SCSI target port ID.
*/
static void
bfad_im_get_starget_port_id(struct scsi_target *starget)
{
struct Scsi_Host *shost;
struct bfad_im_port_s *im_port;
struct bfad_s *bfad;
struct bfad_itnim_s *itnim = NULL;
u32 fc_id = -1;
unsigned long flags;
shost = dev_to_shost(starget->dev.parent);
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
itnim = bfad_get_itnim(im_port, starget->id);
if (itnim)
fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
fc_starget_port_id(starget) = fc_id;
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}
/*
* FC transport template entry, get SCSI target nwwn.
*/
static void
bfad_im_get_starget_node_name(struct scsi_target *starget)
{
struct Scsi_Host *shost;
struct bfad_im_port_s *im_port;
struct bfad_s *bfad;
struct bfad_itnim_s *itnim = NULL;
u64 node_name = 0;
unsigned long flags;
shost = dev_to_shost(starget->dev.parent);
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
itnim = bfad_get_itnim(im_port, starget->id);
if (itnim)
node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);
fc_starget_node_name(starget) = cpu_to_be64(node_name);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}
/*
* FC transport template entry, get SCSI target pwwn.
*/
static void
bfad_im_get_starget_port_name(struct scsi_target *starget)
{
struct Scsi_Host *shost;
struct bfad_im_port_s *im_port;
struct bfad_s *bfad;
struct bfad_itnim_s *itnim = NULL;
u64 port_name = 0;
unsigned long flags;
shost = dev_to_shost(starget->dev.parent);
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
itnim = bfad_get_itnim(im_port, starget->id);
if (itnim)
port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
fc_starget_port_name(starget) = cpu_to_be64(port_name);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}
/*
* FC transport template entry, get SCSI host port ID.
*/
static void
bfad_im_get_host_port_id(struct Scsi_Host *shost)
{
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_port_s *port = im_port->port;
fc_host_port_id(shost) =
bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
}
/*
* FC transport template entry, get SCSI host port type.
*/
static void
bfad_im_get_host_port_type(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_lport_attr_s port_attr;
bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
switch (port_attr.port_type) {
case BFA_PORT_TYPE_NPORT:
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
break;
case BFA_PORT_TYPE_NLPORT:
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
break;
case BFA_PORT_TYPE_P2P:
fc_host_port_type(shost) = FC_PORTTYPE_PTP;
break;
case BFA_PORT_TYPE_LPORT:
fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
break;
default:
fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
break;
}
}
/*
* FC transport template entry, get SCSI host port state.
*/
static void
bfad_im_get_host_port_state(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_port_attr_s attr;
bfa_fcport_get_attr(&bfad->bfa, &attr);
switch (attr.port_state) {
case BFA_PORT_ST_LINKDOWN:
fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
break;
case BFA_PORT_ST_LINKUP:
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
break;
case BFA_PORT_ST_DISABLED:
case BFA_PORT_ST_STOPPED:
case BFA_PORT_ST_IOCDOWN:
case BFA_PORT_ST_IOCDIS:
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
break;
case BFA_PORT_ST_UNINIT:
case BFA_PORT_ST_ENABLING_QWAIT:
case BFA_PORT_ST_ENABLING:
case BFA_PORT_ST_DISABLING_QWAIT:
case BFA_PORT_ST_DISABLING:
default:
fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
break;
}
}
/*
* FC transport template entry, get SCSI host active fc4s.
*/
static void
bfad_im_get_host_active_fc4s(struct Scsi_Host *shost)
{
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_port_s *port = im_port->port;
memset(fc_host_active_fc4s(shost), 0,
sizeof(fc_host_active_fc4s(shost)));
if (port->supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
fc_host_active_fc4s(shost)[2] = 1;
fc_host_active_fc4s(shost)[7] = 1;
}
/*
* FC transport template entry, get SCSI host link speed.
*/
static void
bfad_im_get_host_speed(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_port_attr_s attr;
bfa_fcport_get_attr(&bfad->bfa, &attr);
switch (attr.speed) {
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;
case BFA_PORT_SPEED_4GBPS:
fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
break;
case BFA_PORT_SPEED_2GBPS:
fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
break;
case BFA_PORT_SPEED_1GBPS:
fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
break;
default:
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
}
}
/*
* FC transport template entry, get SCSI host port type.
*/
static void
bfad_im_get_host_fabric_name(struct Scsi_Host *shost)
{
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_port_s *port = im_port->port;
wwn_t fabric_nwwn = 0;
fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port);
fc_host_fabric_name(shost) = cpu_to_be64(fabric_nwwn);
}
/*
* FC transport template entry, get BFAD statistics.
*/
static struct fc_host_statistics *
bfad_im_get_stats(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;
union bfa_port_stats_u *fcstats;
struct fc_host_statistics *hstats;
bfa_status_t rc;
unsigned long flags;
fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL);
if (fcstats == NULL)
return NULL;
hstats = &bfad->link_stats;
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
memset(hstats, 0, sizeof(struct fc_host_statistics));
rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
fcstats, bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK)
return NULL;
wait_for_completion(&fcomp.comp);
/* Fill the fc_host_statistics structure */
hstats->seconds_since_last_reset = fcstats->fc.secs_reset;
hstats->tx_frames = fcstats->fc.tx_frames;
hstats->tx_words = fcstats->fc.tx_words;
hstats->rx_frames = fcstats->fc.rx_frames;
hstats->rx_words = fcstats->fc.rx_words;
hstats->lip_count = fcstats->fc.lip_count;
hstats->nos_count = fcstats->fc.nos_count;
hstats->error_frames = fcstats->fc.error_frames;
hstats->dumped_frames = fcstats->fc.dropped_frames;
hstats->link_failure_count = fcstats->fc.link_failures;
hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs;
hstats->loss_of_signal_count = fcstats->fc.loss_of_signals;
hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs;
hstats->invalid_crc_count = fcstats->fc.invalid_crcs;
kfree(fcstats);
return hstats;
}
/*
* FC transport template entry, reset BFAD statistics.
*/
static void
bfad_im_reset_stats(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;
bfa_status_t rc;
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp,
&fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK)
return;
wait_for_completion(&fcomp.comp);
return;
}
/*
* 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)
{
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;
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
bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)
{
char *vname = fc_vport->symbolic_name;
struct Scsi_Host *shost = fc_vport->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_lport_cfg_s port_cfg;
struct bfad_vport_s *vp;
int status = 0, rc;
unsigned long flags;
memset(&port_cfg, 0, sizeof(port_cfg));
u64_to_wwn(fc_vport->node_name, (u8 *)&port_cfg.nwwn);
u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn);
if (strlen(vname) > 0)
strcpy((char *)&port_cfg.sym_name, vname);
port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
spin_lock_irqsave(&bfad->bfad_lock, flags);
list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) {
if (port_cfg.pwwn ==
vp->fcs_vport.lport.port_cfg.pwwn) {
port_cfg.preboot_vp =
vp->fcs_vport.lport.port_cfg.preboot_vp;
break;
}
}
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev);
if (rc == BFA_STATUS_OK) {
struct bfad_vport_s *vport;
struct bfa_fcs_vport_s *fcs_vport;
struct Scsi_Host *vshost;
spin_lock_irqsave(&bfad->bfad_lock, flags);
fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0,
port_cfg.pwwn);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (fcs_vport == NULL)
return VPCERR_BAD_WWN;
fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
if (disable) {
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_fcs_vport_stop(fcs_vport);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
}
vport = fcs_vport->vport_drv;
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)
return VPCERR_BAD_WWN;
else if (rc == BFA_STATUS_VPORT_EXISTS)
return VPCERR_BAD_WWN;
else if (rc == BFA_STATUS_VPORT_MAX)
return VPCERR_NO_FABRIC_SUPP;
else if (rc == BFA_STATUS_VPORT_WWN_BP)
return VPCERR_BAD_WWN;
else
return FC_VPORT_FAILED;
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)
{
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 bfad_port_s *port;
struct bfa_fcs_vport_s *fcs_vport;
struct Scsi_Host *vshost;
wwn_t pwwn;
int rc;
unsigned long flags;
struct completion fcomp;
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;
vshost = vport->drv_port.im_port->shost;
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 VPCERR_BAD_WWN;
vport->drv_port.flags |= BFAD_PORT_DELETE;
vport->comp_del = &fcomp;
init_completion(vport->comp_del);
spin_lock_irqsave(&bfad->bfad_lock, flags);
rc = bfa_fcs_vport_delete(&vport->fcs_vport);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc == BFA_STATUS_PBC) {
vport->drv_port.flags &= ~BFAD_PORT_DELETE;
vport->comp_del = NULL;
return -1;
}
wait_for_completion(vport->comp_del);
bfad_scsi_host_free(bfad, im_port);
list_del(&vport->list_entry);
kfree(vport);
return 0;
}
static int
bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable)
{
struct bfad_vport_s *vport;
struct bfad_s *bfad;
struct bfa_fcs_vport_s *fcs_vport;
struct Scsi_Host *vshost;
wwn_t pwwn;
unsigned long flags;
vport = (struct bfad_vport_s *)fc_vport->dd_data;
bfad = vport->drv_port.bfad;
vshost = vport->drv_port.im_port->shost;
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 VPCERR_BAD_WWN;
if (disable) {
bfa_fcs_vport_stop(fcs_vport);
fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
} else {
bfa_fcs_vport_start(fcs_vport);
fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
}
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 */
.get_starget_port_id = bfad_im_get_starget_port_id,
.show_starget_port_id = 1,
.get_starget_node_name = bfad_im_get_starget_node_name,
.show_starget_node_name = 1,
.get_starget_port_name = bfad_im_get_starget_port_name,
.show_starget_port_name = 1,
/* Host dynamic attribute */
.get_host_port_id = bfad_im_get_host_port_id,
.show_host_port_id = 1,
/* Host fixed attributes */
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
.show_host_supported_fc4s = 1,
.show_host_supported_speeds = 1,
.show_host_maxframe_size = 1,
/* More host dynamic attributes */
.show_host_port_type = 1,
.get_host_port_type = bfad_im_get_host_port_type,
.show_host_port_state = 1,
.get_host_port_state = bfad_im_get_host_port_state,
.show_host_active_fc4s = 1,
.get_host_active_fc4s = bfad_im_get_host_active_fc4s,
.show_host_speed = 1,
.get_host_speed = bfad_im_get_host_speed,
.show_host_fabric_name = 1,
.get_host_fabric_name = bfad_im_get_host_fabric_name,
.show_host_symbolic_name = 1,
/* Statistics */
.get_fc_host_stats = bfad_im_get_stats,
.reset_fc_host_stats = bfad_im_reset_stats,
/* Allocation length for host specific data */
.dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
/* Remote port fixed attributes */
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.show_rport_dev_loss_tmo = 1,
.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 = {
/* Target dynamic attributes */
.get_starget_port_id = bfad_im_get_starget_port_id,
.show_starget_port_id = 1,
.get_starget_node_name = bfad_im_get_starget_node_name,
.show_starget_node_name = 1,
.get_starget_port_name = bfad_im_get_starget_port_name,
.show_starget_port_name = 1,
/* Host dynamic attribute */
.get_host_port_id = bfad_im_get_host_port_id,
.show_host_port_id = 1,
/* Host fixed attributes */
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
.show_host_supported_fc4s = 1,
.show_host_supported_speeds = 1,
.show_host_maxframe_size = 1,
/* More host dynamic attributes */
.show_host_port_type = 1,
.get_host_port_type = bfad_im_get_host_port_type,
.show_host_port_state = 1,
.get_host_port_state = bfad_im_get_host_port_state,
.show_host_active_fc4s = 1,
.get_host_active_fc4s = bfad_im_get_host_active_fc4s,
.show_host_speed = 1,
.get_host_speed = bfad_im_get_host_speed,
.show_host_fabric_name = 1,
.get_host_fabric_name = bfad_im_get_host_fabric_name,
.show_host_symbolic_name = 1,
/* Statistics */
.get_fc_host_stats = bfad_im_get_stats,
.reset_fc_host_stats = bfad_im_reset_stats,
/* Allocation length for host specific data */
.dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
/* Remote port fixed attributes */
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.show_rport_dev_loss_tmo = 1,
.set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
};
/*
* Scsi_Host_attrs SCSI host attributes
*/
static ssize_t
bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
return snprintf(buf, PAGE_SIZE, "%s\n", serial_num);
}
static ssize_t
bfad_im_model_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
char model[BFA_ADAPTER_MODEL_NAME_LEN];
bfa_get_adapter_model(&bfad->bfa, model);
return snprintf(buf, PAGE_SIZE, "%s\n", model);
}
static ssize_t
bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
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");
else if (!strcmp(model, "Brocade-825"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 8Gbps PCIe dual port FC HBA");
else if (!strcmp(model, "Brocade-42B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 4Gbps PCIe dual port FC HBA for HP");
else if (!strcmp(model, "Brocade-82B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"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");
else if (!strcmp(model, "Brocade-1020"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 10Gbps dual port CNA");
else if (!strcmp(model, "Brocade-1007"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"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");
else if (!strcmp(model, "Brocade-815"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 8Gbps PCIe single port FC HBA");
else if (!strcmp(model, "Brocade-41B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 4Gbps PCIe single port FC HBA for HP");
else if (!strcmp(model, "Brocade-81B"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"Brocade 8Gbps PCIe single port FC HBA for HP");
else if (!strcmp(model, "Brocade-804"))
snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
"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 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");
return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
}
static ssize_t
bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_port_s *port = im_port->port;
u64 nwwn;
nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
return snprintf(buf, PAGE_SIZE, "0x%llx\n", cpu_to_be64(nwwn));
}
static ssize_t
bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
struct bfa_lport_attr_s port_attr;
char symname[BFA_SYMNAME_MAXLEN];
bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
strncpy(symname, port_attr.port_cfg.sym_name.symname,
BFA_SYMNAME_MAXLEN);
return snprintf(buf, PAGE_SIZE, "%s\n", symname);
}
static ssize_t
bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
char hw_ver[BFA_VERSION_LEN];
bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver);
}
static ssize_t
bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
}
static ssize_t
bfad_im_optionrom_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
char optrom_ver[BFA_VERSION_LEN];
bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver);
}
static ssize_t
bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
char fw_ver[BFA_VERSION_LEN];
bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver);
}
static ssize_t
bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
return snprintf(buf, PAGE_SIZE, "%d\n",
bfa_get_nports(&bfad->bfa));
}
static ssize_t
bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
}
static ssize_t
bfad_im_num_of_discovered_ports_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_port_s *port = im_port->port;
struct bfad_s *bfad = im_port->bfad;
int nrports = 2048;
struct bfa_rport_qualifier_s *rports = NULL;
unsigned long flags;
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_rport_quals(port->fcs_port, rports, &nrports);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
kfree(rports);
return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
}
static DEVICE_ATTR(serial_number, S_IRUGO,
bfad_im_serial_num_show, NULL);
static DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL);
static DEVICE_ATTR(model_description, S_IRUGO,
bfad_im_model_desc_show, NULL);
static DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL);
static DEVICE_ATTR(symbolic_name, S_IRUGO,
bfad_im_symbolic_name_show, NULL);
static DEVICE_ATTR(hardware_version, S_IRUGO,
bfad_im_hw_version_show, NULL);
static DEVICE_ATTR(driver_version, S_IRUGO,
bfad_im_drv_version_show, NULL);
static DEVICE_ATTR(option_rom_version, S_IRUGO,
bfad_im_optionrom_version_show, NULL);
static DEVICE_ATTR(firmware_version, S_IRUGO,
bfad_im_fw_version_show, NULL);
static DEVICE_ATTR(number_of_ports, S_IRUGO,
bfad_im_num_of_ports_show, NULL);
static DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL);
static DEVICE_ATTR(number_of_discovered_ports, S_IRUGO,
bfad_im_num_of_discovered_ports_show, NULL);
struct device_attribute *bfad_im_host_attrs[] = {
&dev_attr_serial_number,
&dev_attr_model,
&dev_attr_model_description,
&dev_attr_node_name,
&dev_attr_symbolic_name,
&dev_attr_hardware_version,
&dev_attr_driver_version,
&dev_attr_option_rom_version,
&dev_attr_firmware_version,
&dev_attr_number_of_ports,
&dev_attr_driver_name,
&dev_attr_number_of_discovered_ports,
NULL,
};
struct device_attribute *bfad_im_vport_attrs[] = {
&dev_attr_serial_number,
&dev_attr_model,
&dev_attr_model_description,
&dev_attr_node_name,
&dev_attr_symbolic_name,
&dev_attr_hardware_version,
&dev_attr_driver_version,
&dev_attr_option_rom_version,
&dev_attr_firmware_version,
&dev_attr_number_of_ports,
&dev_attr_driver_name,
&dev_attr_number_of_discovered_ports,
NULL,
};

3593
drivers/scsi/bfa/bfad_bsg.c Normal file

File diff suppressed because it is too large Load diff

836
drivers/scsi/bfa/bfad_bsg.h Normal file
View file

@ -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 */

View file

@ -0,0 +1,550 @@
/*
* 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/debugfs.h>
#include <linux/export.h>
#include "bfad_drv.h"
#include "bfad_im.h"
/*
* BFA debufs interface
*
* To access the interface, debugfs file system should be mounted
* if not already mounted using:
* mount -t debugfs none /sys/kernel/debug
*
* BFA Hierarchy:
* - bfa/pci_dev:<pci_name>
* where the pci_name corresponds to the one under /sys/bus/pci/drivers/bfa
*
* 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.
* regwr: To write one word to chip register
* regrd: To read one or more words from chip register.
*/
struct bfad_debug_info {
char *debug_buffer;
void *i_private;
int buffer_len;
};
static int
bfad_debugfs_open_drvtrc(struct inode *inode, struct file *file)
{
struct bfad_port_s *port = inode->i_private;
struct bfad_s *bfad = port->bfad;
struct bfad_debug_info *debug;
debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL);
if (!debug)
return -ENOMEM;
debug->debug_buffer = (void *) bfad->trcmod;
debug->buffer_len = sizeof(struct bfa_trc_mod_s);
file->private_data = debug;
return 0;
}
static int
bfad_debugfs_open_fwtrc(struct inode *inode, struct file *file)
{
struct bfad_port_s *port = inode->i_private;
struct bfad_s *bfad = port->bfad;
struct bfad_debug_info *fw_debug;
unsigned long flags;
int rc;
fw_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL);
if (!fw_debug)
return -ENOMEM;
fw_debug->buffer_len = sizeof(struct bfa_trc_mod_s);
fw_debug->debug_buffer = vmalloc(fw_debug->buffer_len);
if (!fw_debug->debug_buffer) {
kfree(fw_debug);
printk(KERN_INFO "bfad[%d]: Failed to allocate fwtrc buffer\n",
bfad->inst_no);
return -ENOMEM;
}
memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);
spin_lock_irqsave(&bfad->bfad_lock, flags);
rc = bfa_ioc_debug_fwtrc(&bfad->bfa.ioc,
fw_debug->debug_buffer,
&fw_debug->buffer_len);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK) {
vfree(fw_debug->debug_buffer);
fw_debug->debug_buffer = NULL;
kfree(fw_debug);
printk(KERN_INFO "bfad[%d]: Failed to collect fwtrc\n",
bfad->inst_no);
return -ENOMEM;
}
file->private_data = fw_debug;
return 0;
}
static int
bfad_debugfs_open_fwsave(struct inode *inode, struct file *file)
{
struct bfad_port_s *port = inode->i_private;
struct bfad_s *bfad = port->bfad;
struct bfad_debug_info *fw_debug;
unsigned long flags;
int rc;
fw_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL);
if (!fw_debug)
return -ENOMEM;
fw_debug->buffer_len = sizeof(struct bfa_trc_mod_s);
fw_debug->debug_buffer = vmalloc(fw_debug->buffer_len);
if (!fw_debug->debug_buffer) {
kfree(fw_debug);
printk(KERN_INFO "bfad[%d]: Failed to allocate fwsave buffer\n",
bfad->inst_no);
return -ENOMEM;
}
memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);
spin_lock_irqsave(&bfad->bfad_lock, flags);
rc = bfa_ioc_debug_fwsave(&bfad->bfa.ioc,
fw_debug->debug_buffer,
&fw_debug->buffer_len);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK) {
vfree(fw_debug->debug_buffer);
fw_debug->debug_buffer = NULL;
kfree(fw_debug);
printk(KERN_INFO "bfad[%d]: Failed to collect fwsave\n",
bfad->inst_no);
return -ENOMEM;
}
file->private_data = fw_debug;
return 0;
}
static int
bfad_debugfs_open_reg(struct inode *inode, struct file *file)
{
struct bfad_debug_info *reg_debug;
reg_debug = kzalloc(sizeof(struct bfad_debug_info), GFP_KERNEL);
if (!reg_debug)
return -ENOMEM;
reg_debug->i_private = inode->i_private;
file->private_data = reg_debug;
return 0;
}
/* Changes the current file position */
static loff_t
bfad_debugfs_lseek(struct file *file, loff_t offset, int orig)
{
struct bfad_debug_info *debug = file->private_data;
return fixed_size_llseek(file, offset, orig,
debug->buffer_len);
}
static ssize_t
bfad_debugfs_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *pos)
{
struct bfad_debug_info *debug = file->private_data;
if (!debug || !debug->debug_buffer)
return 0;
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(__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)
{
u8 area;
/* check [16:15] */
area = (offset >> 15) & 0x7;
if (area == 0) {
/* PCIe core register */
if ((offset + (len<<2)) > 0x8000) /* 8k dwords or 32KB */
return BFA_STATUS_EINVAL;
} else if (area == 0x1) {
/* CB 32 KB memory page */
if ((offset + (len<<2)) > 0x10000) /* 8k dwords or 32KB */
return BFA_STATUS_EINVAL;
} else {
/* CB register space 64KB */
if ((offset + (len<<2)) > BFA_REG_ADDRMSK(&bfa->ioc))
return BFA_STATUS_EINVAL;
}
return BFA_STATUS_OK;
}
static ssize_t
bfad_debugfs_read_regrd(struct file *file, char __user *buf,
size_t nbytes, loff_t *pos)
{
struct bfad_debug_info *regrd_debug = file->private_data;
struct bfad_port_s *port = (struct bfad_port_s *)regrd_debug->i_private;
struct bfad_s *bfad = port->bfad;
ssize_t rc;
if (!bfad->regdata)
return 0;
rc = simple_read_from_buffer(buf, nbytes, pos,
bfad->regdata, bfad->reglen);
if ((*pos + nbytes) >= bfad->reglen) {
kfree(bfad->regdata);
bfad->regdata = NULL;
bfad->reglen = 0;
}
return rc;
}
static ssize_t
bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
size_t nbytes, loff_t *ppos)
{
struct bfad_debug_info *regrd_debug = file->private_data;
struct bfad_port_s *port = (struct bfad_port_s *)regrd_debug->i_private;
struct bfad_s *bfad = port->bfad;
struct bfa_s *bfa = &bfad->bfa;
struct bfa_ioc_s *ioc = &bfa->ioc;
int addr, len, rc, i;
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;
}
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;
bfad->regdata = kzalloc(len << 2, GFP_KERNEL);
if (!bfad->regdata) {
printk(KERN_INFO "bfad[%d]: Failed to allocate regrd buffer\n",
bfad->inst_no);
return -ENOMEM;
}
bfad->reglen = len << 2;
rb = bfa_ioc_bar0(ioc);
addr &= BFA_REG_ADDRMSK(ioc);
/* offset and len sanity check */
rc = bfad_reg_offset_check(bfa, addr, len);
if (rc) {
printk(KERN_INFO "bfad[%d]: Failed reg offset check\n",
bfad->inst_no);
kfree(bfad->regdata);
bfad->regdata = NULL;
bfad->reglen = 0;
return -EINVAL;
}
reg_addr = rb + addr;
regbuf = (u32 *)bfad->regdata;
spin_lock_irqsave(&bfad->bfad_lock, flags);
for (i = 0; i < len; i++) {
*regbuf = readl(reg_addr);
regbuf++;
reg_addr += sizeof(u32);
}
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return nbytes;
}
static ssize_t
bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
size_t nbytes, loff_t *ppos)
{
struct bfad_debug_info *debug = file->private_data;
struct bfad_port_s *port = (struct bfad_port_s *)debug->i_private;
struct bfad_s *bfad = port->bfad;
struct bfa_s *bfa = &bfad->bfa;
struct bfa_ioc_s *ioc = &bfa->ioc;
int addr, val, rc;
void __iomem *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;
}
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(ioc); /* offset only 17 bit and word align */
/* offset and len sanity check */
rc = bfad_reg_offset_check(bfa, addr, 1);
if (rc) {
printk(KERN_INFO
"bfad[%d]: Failed reg offset check\n",
bfad->inst_no);
return -EINVAL;
}
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);
return nbytes;
}
static int
bfad_debugfs_release(struct inode *inode, struct file *file)
{
struct bfad_debug_info *debug = file->private_data;
if (!debug)
return 0;
file->private_data = NULL;
kfree(debug);
return 0;
}
static int
bfad_debugfs_release_fwtrc(struct inode *inode, struct file *file)
{
struct bfad_debug_info *fw_debug = file->private_data;
if (!fw_debug)
return 0;
if (fw_debug->debug_buffer)
vfree(fw_debug->debug_buffer);
file->private_data = NULL;
kfree(fw_debug);
return 0;
}
static const struct file_operations bfad_debugfs_op_drvtrc = {
.owner = THIS_MODULE,
.open = bfad_debugfs_open_drvtrc,
.llseek = bfad_debugfs_lseek,
.read = bfad_debugfs_read,
.release = bfad_debugfs_release,
};
static const struct file_operations bfad_debugfs_op_fwtrc = {
.owner = THIS_MODULE,
.open = bfad_debugfs_open_fwtrc,
.llseek = bfad_debugfs_lseek,
.read = bfad_debugfs_read,
.release = bfad_debugfs_release_fwtrc,
};
static const struct file_operations bfad_debugfs_op_fwsave = {
.owner = THIS_MODULE,
.open = bfad_debugfs_open_fwsave,
.llseek = bfad_debugfs_lseek,
.read = bfad_debugfs_read,
.release = bfad_debugfs_release_fwtrc,
};
static const struct file_operations bfad_debugfs_op_regrd = {
.owner = THIS_MODULE,
.open = bfad_debugfs_open_reg,
.llseek = bfad_debugfs_lseek,
.read = bfad_debugfs_read_regrd,
.write = bfad_debugfs_write_regrd,
.release = bfad_debugfs_release,
};
static const struct file_operations bfad_debugfs_op_regwr = {
.owner = THIS_MODULE,
.open = bfad_debugfs_open_reg,
.llseek = bfad_debugfs_lseek,
.write = bfad_debugfs_write_regwr,
.release = bfad_debugfs_release,
};
struct bfad_debugfs_entry {
const char *name;
umode_t mode;
const struct file_operations *fops;
};
static const struct bfad_debugfs_entry bfad_debugfs_files[] = {
{ "drvtrc", S_IFREG|S_IRUGO, &bfad_debugfs_op_drvtrc, },
{ "fwtrc", S_IFREG|S_IRUGO, &bfad_debugfs_op_fwtrc, },
{ "fwsave", S_IFREG|S_IRUGO, &bfad_debugfs_op_fwsave, },
{ "regrd", S_IFREG|S_IRUGO|S_IWUSR, &bfad_debugfs_op_regrd, },
{ "regwr", S_IFREG|S_IWUSR, &bfad_debugfs_op_regwr, },
};
static struct dentry *bfa_debugfs_root;
static atomic_t bfa_debugfs_port_count;
inline void
bfad_debugfs_init(struct bfad_port_s *port)
{
struct bfad_s *bfad = port->bfad;
const struct bfad_debugfs_entry *file;
char name[64];
int i;
if (!bfa_debugfs_enable)
return;
/* Setup the BFA debugfs root directory*/
if (!bfa_debugfs_root) {
bfa_debugfs_root = debugfs_create_dir("bfa", NULL);
atomic_set(&bfa_debugfs_port_count, 0);
if (!bfa_debugfs_root) {
printk(KERN_WARNING
"BFA debugfs root dir creation failed\n");
goto err;
}
}
/* 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 %s: debugfs root creation failed\n",
bfad->pci_name);
goto err;
}
atomic_inc(&bfa_debugfs_port_count);
for (i = 0; i < ARRAY_SIZE(bfad_debugfs_files); i++) {
file = &bfad_debugfs_files[i];
bfad->bfad_dentry_files[i] =
debugfs_create_file(file->name,
file->mode,
port->port_debugfs_root,
port,
file->fops);
if (!bfad->bfad_dentry_files[i]) {
printk(KERN_WARNING
"bfa %s: debugfs %s creation failed\n",
bfad->pci_name, file->name);
goto err;
}
}
}
err:
return;
}
inline void
bfad_debugfs_exit(struct bfad_port_s *port)
{
struct bfad_s *bfad = port->bfad;
int i;
for (i = 0; i < ARRAY_SIZE(bfad_debugfs_files); i++) {
if (bfad->bfad_dentry_files[i]) {
debugfs_remove(bfad->bfad_dentry_files[i]);
bfad->bfad_dentry_files[i] = NULL;
}
}
/* 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;
atomic_dec(&bfa_debugfs_port_count);
}
/* Remove the BFA debugfs root directory */
if (atomic_read(&bfa_debugfs_port_count) == 0) {
debugfs_remove(bfa_debugfs_root);
bfa_debugfs_root = NULL;
}
}

360
drivers/scsi/bfa/bfad_drv.h Normal file
View file

@ -0,0 +1,360 @@
/*
* 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.
*/
/*
* Contains base driver definitions.
*/
/*
* bfa_drv.h Linux driver data structures.
*/
#ifndef __BFAD_DRV_H__
#define __BFAD_DRV_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"
#include "bfa_defs_fcs.h"
#include "bfa_plog.h"
#include "bfa_cs.h"
#define BFAD_DRIVER_NAME "bfa"
#ifdef BFA_DRIVER_VERSION
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
#else
#define BFAD_DRIVER_VERSION "3.2.23.0"
#endif
#define BFAD_PROTO_NAME FCPI_NAME
#define BFAD_IRQ_FLAGS IRQF_SHARED
#ifndef FC_PORTSPEED_8GBIT
#define FC_PORTSPEED_8GBIT 0x10
#endif
/*
* BFAD flags
*/
#define BFAD_MSIX_ON 0x00000001
#define BFAD_HAL_INIT_DONE 0x00000002
#define BFAD_DRV_INIT_DONE 0x00000004
#define BFAD_CFG_PPORT_DONE 0x00000008
#define BFAD_HAL_START_DONE 0x00000010
#define BFAD_PORT_ONLINE 0x00000020
#define BFAD_RPORT_ONLINE 0x00000040
#define BFAD_FCS_INIT_DONE 0x00000080
#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
*/
#define SCSI_SCAN_DELAY HZ
#define BFAD_STOP_TIMEOUT 30
#define BFAD_SUSPEND_TIMEOUT BFAD_STOP_TIMEOUT
/*
* BFAD configuration parameter default values
*/
#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
#define MAX_MSIX_ENTRY 22
struct bfad_msix_s {
struct bfad_s *bfad;
struct msix_entry msix;
char name[32];
};
/*
* Only append to the enums defined here to avoid any versioning
* needed between trace utility and driver version
*/
enum {
BFA_TRC_LDRV_BFAD = 1,
BFA_TRC_LDRV_IM = 2,
BFA_TRC_LDRV_BSG = 3,
};
enum bfad_port_pvb_type {
BFAD_PORT_PHYS_BASE = 0,
BFAD_PORT_PHYS_VPORT = 1,
BFAD_PORT_VF_BASE = 2,
BFAD_PORT_VF_VPORT = 3,
};
/*
* PORT data structure
*/
struct bfad_port_s {
struct list_head list_entry;
struct bfad_s *bfad;
struct bfa_fcs_lport_s *fcs_port;
u32 roles;
s32 flags;
u32 supported_fc4s;
enum bfad_port_pvb_type pvb_type;
struct bfad_im_port_s *im_port; /* IM specific data */
/* port debugfs specific data */
struct dentry *port_debugfs_root;
};
/*
* VPORT data structure
*/
struct bfad_vport_s {
struct bfad_port_s drv_port;
struct bfa_fcs_vport_s fcs_vport;
struct completion *comp_del;
struct list_head list_entry;
};
/*
* VF data structure
*/
struct bfad_vf_s {
bfa_fcs_vf_t fcs_vf;
struct bfad_port_s base_port; /* base port for vf */
struct bfad_s *bfad;
};
struct bfad_cfg_param_s {
u32 rport_del_timeout;
u32 ioc_queue_depth;
u32 lun_queue_depth;
u32 io_max_sge;
u32 binding_method;
};
union bfad_tmp_buf {
/* From struct bfa_adapter_attr_s */
char manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
char model[BFA_ADAPTER_MODEL_NAME_LEN];
char fw_ver[BFA_VERSION_LEN];
char optrom_ver[BFA_VERSION_LEN];
/* From struct bfa_ioc_pci_attr_s */
u8 chip_rev[BFA_IOC_CHIP_REV_LEN]; /* chip revision */
wwn_t wwn[BFA_FCS_MAX_LPORTS];
};
/*
* BFAD (PCI function) data structure
*/
struct bfad_s {
bfa_sm_t sm; /* state machine */
struct list_head list_entry;
struct bfa_s bfa;
struct bfa_fcs_s bfa_fcs;
struct pci_dev *pcidev;
const char *pci_name;
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 */
struct bfa_meminfo_s meminfo;
struct bfa_iocfc_cfg_s ioc_cfg;
u32 inst_no; /* BFAD instance number */
u32 bfad_flags;
spinlock_t bfad_lock;
struct task_struct *bfad_tsk;
struct bfad_cfg_param_s cfg_data;
struct bfad_msix_s msix_tab[MAX_MSIX_ENTRY];
int nvec;
char adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
char port_name[BFA_ADAPTER_SYM_NAME_LEN];
struct timer_list hal_tmo;
unsigned long hs_start;
struct bfad_im_s *im; /* IM specific data */
struct bfa_trc_mod_s *trcmod;
struct bfa_plog_s plog_buf;
int ref_count;
union bfad_tmp_buf tmp_buf;
struct fc_host_statistics link_stats;
struct list_head pbc_vport_list;
/* debugfs specific data */
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 */
enum bfad_sm_event {
BFAD_E_CREATE = 1,
BFAD_E_KTHREAD_CREATE_FAILED = 2,
BFAD_E_INIT = 3,
BFAD_E_INIT_SUCCESS = 4,
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
};
/*
* RPORT data structure
*/
struct bfad_rport_s {
struct bfa_fcs_rport_s fcs_rport;
};
struct bfad_buf_info {
void *virt;
dma_addr_t phys;
u32 size;
};
struct bfad_fcxp {
struct bfad_port_s *port;
struct bfa_rport_s *bfa_rport;
bfa_status_t req_status;
u16 tag;
u16 rsp_len;
u16 rsp_maxlen;
u8 use_ireqbuf;
u8 use_irspbuf;
u32 num_req_sgles;
u32 num_rsp_sgles;
struct fchs_s fchs;
void *reqbuf_info;
void *rspbuf_info;
struct bfa_sge_s *req_sge;
struct bfa_sge_s *rsp_sge;
fcxp_send_cb_t send_cbfn;
void *send_cbarg;
void *bfa_fcxp;
struct completion comp;
};
struct bfad_hal_comp {
bfa_status_t status;
struct completion comp;
};
#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)
bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
struct bfa_lport_cfg_s *port_cfg,
struct device *dev);
bfa_status_t bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
struct bfa_lport_cfg_s *port_cfg);
bfa_status_t bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role);
bfa_status_t bfad_drv_init(struct bfad_s *bfad);
bfa_status_t bfad_start_ops(struct bfad_s *bfad);
void bfad_drv_start(struct bfad_s *bfad);
void bfad_uncfg_pport(struct bfad_s *bfad);
void bfad_stop(struct bfad_s *bfad);
void bfad_fcs_stop(struct bfad_s *bfad);
void bfad_remove_intr(struct bfad_s *bfad);
void bfad_hal_mem_release(struct bfad_s *bfad);
void bfad_hcb_comp(void *arg, bfa_status_t status);
int bfad_setup_intr(struct bfad_s *bfad);
void bfad_remove_intr(struct bfad_s *bfad);
void bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg);
bfa_status_t bfad_hal_mem_alloc(struct bfad_s *bfad);
void bfad_bfa_tmo(unsigned long data);
void bfad_init_timer(struct bfad_s *bfad);
int bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad);
void bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad);
void bfad_drv_uninit(struct bfad_s *bfad);
int bfad_worker(void *ptr);
void bfad_debugfs_init(struct bfad_port_s *port);
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_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;
extern struct pci_device_id bfad_id_table[];
extern struct list_head bfad_list;
extern char *os_name;
extern char *os_patch;
extern char *host_name;
extern int num_rports;
extern int num_ios;
extern int num_tms;
extern int num_fcxps;
extern int num_ufbufs;
extern int reqq_size;
extern int rspq_size;
extern int num_sgpgs;
extern int rport_del_timeout;
extern int bfa_lun_queue_depth;
extern int bfa_io_max_sge;
extern int bfa_log_level;
extern int ioc_auto_recover;
extern int bfa_linkup_delay;
extern int msix_disable_cb;
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;
#endif /* __BFAD_DRV_H__ */

1328
drivers/scsi/bfa/bfad_im.c Normal file

File diff suppressed because it is too large Load diff

197
drivers/scsi/bfa/bfad_im.h Normal file
View file

@ -0,0 +1,197 @@
/*
* 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_IM_H__
#define __BFAD_IM_H__
#include "bfa_fcs.h"
#define FCPI_NAME " fcpim"
#ifndef KOBJ_NAME_LEN
#define KOBJ_NAME_LEN 20
#endif
bfa_status_t bfad_im_module_init(void);
void bfad_im_module_exit(void);
bfa_status_t bfad_im_probe(struct bfad_s *bfad);
void bfad_im_probe_undo(struct bfad_s *bfad);
bfa_status_t bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port);
void bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port);
void bfad_im_port_clean(struct bfad_im_port_s *im_port);
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
#define BFAD_TARGET_RESET_TMO 60
#define BFAD_LUN_RESET_TMO 60
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
#define BFA_QUEUE_FULL_RAMP_UP_TIME 120
/*
* itnim flags
*/
#define IO_DONE_BIT 0
struct bfad_itnim_data_s {
struct bfad_itnim_s *itnim;
};
struct bfad_im_port_s {
struct bfad_s *bfad;
struct bfad_port_s *port;
struct work_struct port_delete_work;
int idr_id;
u16 cur_scsi_id;
u16 flags;
struct list_head binding_list;
struct Scsi_Host *shost;
struct list_head itnim_mapped_list;
struct fc_vport *fc_vport;
};
enum bfad_itnim_state {
ITNIM_STATE_NONE,
ITNIM_STATE_ONLINE,
ITNIM_STATE_OFFLINE_PENDING,
ITNIM_STATE_OFFLINE,
ITNIM_STATE_TIMEOUT,
ITNIM_STATE_FREE,
};
/*
* Per itnim data structure
*/
struct bfad_itnim_s {
struct list_head list_entry;
struct bfa_fcs_itnim_s fcs_itnim;
struct work_struct itnim_work;
u32 flags;
enum bfad_itnim_state state;
struct bfad_im_s *im;
struct bfad_im_port_s *im_port;
struct bfad_rport_s *drv_rport;
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;
};
enum bfad_binding_type {
FCP_PWWN_BINDING = 0x1,
FCP_NWWN_BINDING = 0x2,
FCP_FCID_BINDING = 0x3,
};
struct bfad_fcp_binding {
struct list_head list_entry;
enum bfad_binding_type binding_type;
u16 scsi_target_id;
u32 fc_id;
wwn_t nwwn;
wwn_t pwwn;
};
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;
};
#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_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_ramp_up_qdepth(struct bfad_itnim_s *itnim,
struct scsi_device *sdev);
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;
extern struct fc_function_template bfad_im_fc_function_template;
extern struct fc_function_template bfad_im_vport_fc_function_template;
extern struct scsi_transport_template *bfad_im_scsi_transport_template;
extern struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
extern struct device_attribute *bfad_im_host_attrs[];
extern struct device_attribute *bfad_im_vport_attrs[];
irqreturn_t bfad_intx(int irq, void *dev_id);
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

1324
drivers/scsi/bfa/bfi.h Normal file

File diff suppressed because it is too large Load diff

878
drivers/scsi/bfa/bfi_ms.h Normal file
View file

@ -0,0 +1,878 @@
/*
* 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 __BFI_MS_H__
#define __BFI_MS_H__
#include "bfi.h"
#include "bfa_fc.h"
#include "bfa_defs_svc.h"
#pragma pack(1)
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 {
u8 num_cqs; /* Number of CQs to be used */
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
* shadow index pointers.
*/
union bfi_addr_u req_cq_ba[BFI_IOC_MAX_CQS];
union bfi_addr_u req_shadow_ci[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];
__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[BFI_IOIM_SNSBUF_SEGS];
/* IO sense buf base addr segments */
struct bfa_iocfc_intr_attr_s intr_attr; /* IOC interrupt attributes */
};
/*
* Boot target wwn information for this port. This contains either the stored
* or discovered boot target port wwns for the port.
*/
struct bfi_iocfc_bootwwns {
wwn_t wwn[BFA_BOOT_BOOTLUN_MAX];
u8 nwwns;
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;
};
/*
* BFI_IOCFC_H2I_CFG_REQ message
*/
struct bfi_iocfc_cfg_req_s {
struct bfi_mhdr_s mh;
union bfi_addr_u ioc_cfg_dma_addr;
};
/*
* BFI_IOCFC_I2H_CFG_REPLY message
*/
struct bfi_iocfc_cfg_reply_s {
struct bfi_mhdr_s mh; /* Common msg header */
u8 cfg_success; /* cfg reply status */
u8 lpu_bm; /* LPUs assigned for this IOC */
u8 rsvd[2];
};
/*
* BFI_IOCFC_H2I_SET_INTR_REQ message
*/
struct bfi_iocfc_set_intr_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 coalesce; /* enable intr coalescing */
u8 rsvd[3];
__be16 delay; /* delay timer 0..1125us */
__be16 latency; /* latency timer 0..225us */
};
/*
* BFI_IOCFC_H2I_UPDATEQ_REQ message
*/
struct bfi_iocfc_updateq_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u32 reqq_ba; /* reqq base addr */
u32 rspq_ba; /* rspq base addr */
u32 reqq_sci; /* reqq shadow ci */
u32 rspq_spi; /* rspq shadow pi */
};
/*
* BFI_IOCFC_I2H_UPDATEQ_RSP message
*/
struct bfi_iocfc_updateq_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 status; /* updateq status */
u8 rsvd[3];
};
/*
* H2I Messages
*/
union bfi_iocfc_h2i_msg_u {
struct bfi_mhdr_s mh;
struct bfi_iocfc_cfg_req_s cfg_req;
struct bfi_iocfc_updateq_req_s updateq_req;
u32 mboxmsg[BFI_IOC_MSGSZ];
};
/*
* I2H Messages
*/
union bfi_iocfc_i2h_msg_u {
struct bfi_mhdr_s mh;
struct bfi_iocfc_cfg_reply_s cfg_reply;
struct bfi_iocfc_updateq_rsp_s updateq_rsp;
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),
BFI_FCPORT_H2I_DISABLE_REQ = (2),
BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ = (3),
BFI_FCPORT_H2I_STATS_GET_REQ = (4),
BFI_FCPORT_H2I_STATS_CLEAR_REQ = (5),
};
enum bfi_fcport_i2h {
BFI_FCPORT_I2H_ENABLE_RSP = BFA_I2HM(1),
BFI_FCPORT_I2H_DISABLE_RSP = BFA_I2HM(2),
BFI_FCPORT_I2H_SET_SVC_PARAMS_RSP = BFA_I2HM(3),
BFI_FCPORT_I2H_STATS_GET_RSP = BFA_I2HM(4),
BFI_FCPORT_I2H_STATS_CLEAR_RSP = BFA_I2HM(5),
BFI_FCPORT_I2H_EVENT = BFA_I2HM(6),
BFI_FCPORT_I2H_TRUNK_SCN = BFA_I2HM(7),
BFI_FCPORT_I2H_ENABLE_AEN = BFA_I2HM(8),
BFI_FCPORT_I2H_DISABLE_AEN = BFA_I2HM(9),
};
/*
* Generic REQ type
*/
struct bfi_fcport_req_s {
struct bfi_mhdr_s mh; /* msg header */
u32 msgtag; /* msgtag for reply */
};
/*
* Generic RSP type
*/
struct bfi_fcport_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 status; /* port enable status */
u8 rsvd[3];
struct bfa_port_cfg_s port_cfg;/* port configuration */
u32 msgtag; /* msgtag for reply */
};
/*
* BFI_FCPORT_H2I_ENABLE_REQ
*/
struct bfi_fcport_enable_req_s {
struct bfi_mhdr_s mh; /* msg header */
u32 rsvd1;
wwn_t nwwn; /* node wwn of physical port */
wwn_t pwwn; /* port wwn of physical port */
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 */
u8 use_flash_cfg; /* get prot cfg from flash */
u8 rsvd2[3];
};
/*
* BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ
*/
struct bfi_fcport_set_svc_params_req_s {
struct bfi_mhdr_s mh; /* msg header */
__be16 tx_bbcredit; /* Tx credits */
u8 rsvd[2];
};
/*
* BFI_FCPORT_I2H_EVENT
*/
struct bfi_fcport_event_s {
struct bfi_mhdr_s mh; /* common msg header */
struct bfa_port_link_s link_state;
};
/*
* BFI_FCPORT_I2H_TRUNK_SCN
*/
struct bfi_fcport_trunk_link_s {
wwn_t trunk_wwn;
u8 fctl; /* bfa_trunk_link_fctl_t */
u8 state; /* bfa_trunk_link_state_t */
u8 speed; /* bfa_port_speed_t */
u8 rsvd;
__be32 deskew;
};
#define BFI_FCPORT_MAX_LINKS 2
struct bfi_fcport_trunk_scn_s {
struct bfi_mhdr_s mh;
u8 trunk_state; /* bfa_trunk_state_t */
u8 trunk_speed; /* bfa_port_speed_t */
u8 rsvd_a[2];
struct bfi_fcport_trunk_link_s tlink[BFI_FCPORT_MAX_LINKS];
};
/*
* fcport H2I message
*/
union bfi_fcport_h2i_msg_u {
struct bfi_mhdr_s *mhdr;
struct bfi_fcport_enable_req_s *penable;
struct bfi_fcport_req_s *pdisable;
struct bfi_fcport_set_svc_params_req_s *psetsvcparams;
struct bfi_fcport_req_s *pstatsget;
struct bfi_fcport_req_s *pstatsclear;
};
/*
* fcport I2H message
*/
union bfi_fcport_i2h_msg_u {
struct bfi_msg_s *msg;
struct bfi_fcport_rsp_s *penable_rsp;
struct bfi_fcport_rsp_s *pdisable_rsp;
struct bfi_fcport_rsp_s *psetsvcparams_rsp;
struct bfi_fcport_rsp_s *pstatsget_rsp;
struct bfi_fcport_rsp_s *pstatsclear_rsp;
struct bfi_fcport_event_s *event;
struct bfi_fcport_trunk_scn_s *trunk_scn;
};
enum bfi_fcxp_h2i {
BFI_FCXP_H2I_SEND_REQ = 1,
};
enum bfi_fcxp_i2h {
BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
};
#define BFA_FCXP_MAX_SGES 2
/*
* FCXP send request structure
*/
struct bfi_fcxp_send_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
__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_fwtag; /* lport tag */
struct fchs_s fchs; /* request FC header structure */
__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 */
};
/*
* FCXP send response structure
*/
struct bfi_fcxp_send_rsp_s {
struct bfi_mhdr_s mh; /* Common msg header */
__be16 fcxp_tag; /* send request tag */
u8 req_status; /* request status */
u8 rsvd;
__be32 rsp_len; /* actual response length */
__be32 residue_len; /* residual response length */
struct fchs_s fchs; /* response FC header structure */
};
enum bfi_uf_h2i {
BFI_UF_H2I_BUF_POST = 1,
};
enum bfi_uf_i2h {
BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
};
#define BFA_UF_MAX_SGES 2
struct bfi_uf_buf_post_s {
struct bfi_mhdr_s mh; /* Common msg header */
u16 buf_tag; /* buffer tag */
__be16 buf_len; /* total buffer length */
struct bfi_alen_s alen; /* buffer address/len pair */
};
struct bfi_uf_frm_rcvd_s {
struct bfi_mhdr_s mh; /* Common msg header */
u16 buf_tag; /* buffer tag */
u16 rsvd;
u16 frm_len; /* received frame length */
u16 xfr_len; /* tranferred length */
};
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_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 bfa_tag;
u8 alpa;
__be16 pdu_size;
wwn_t pwwn;
wwn_t nwwn;
u8 fdisc;
u8 auth_en;
u8 lps_role;
u8 bb_scn;
u32 vvl_flag;
};
struct bfi_lps_login_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 fw_tag;
u8 status;
u8 lsrjt_rsn;
u8 lsrjt_expl;
wwn_t port_name;
wwn_t node_name;
__be16 bb_credit;
u8 f_port;
u8 npiv_en;
u32 lp_pid:24;
u32 auth_req:8;
mac_t lp_mac;
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 fw_tag;
u8 rsvd[3];
wwn_t port_name;
};
struct bfi_lps_logout_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 bfa_tag;
u8 status;
u8 rsvd[2];
};
struct bfi_lps_cvl_event_s {
struct bfi_mhdr_s mh; /* common msg header */
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 {
struct bfi_msg_s *msg;
struct bfi_lps_login_rsp_s *login_rsp;
struct bfi_lps_logout_rsp_s *logout_rsp;
struct bfi_lps_cvl_event_s *cvl_event;
};
enum bfi_rport_h2i_msgs {
BFI_RPORT_H2I_CREATE_REQ = 1,
BFI_RPORT_H2I_DELETE_REQ = 2,
BFI_RPORT_H2I_SET_SPEED_REQ = 3,
};
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 */
__be16 max_frmsz; /* max rcv pdu size */
u32 pid:24, /* remote port ID */
lp_fwtag:8; /* local port tag */
u32 local_pid:24, /* local port ID */
cisc:8;
u8 fc_class; /* supported FC classes */
u8 vf_en; /* virtual fabric enable */
u16 vf_id; /* virtual fabric ID */
};
struct bfi_rport_create_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u8 status; /* rport creation status */
u8 rsvd[3];
u16 bfa_handle; /* host rport handle */
u16 fw_handle; /* firmware rport handle */
struct bfa_rport_qos_attr_s qos_attr; /* QoS Attributes */
};
struct bfa_rport_speed_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 fw_handle; /* firmware rport handle */
u8 speed; /* rport's speed via RPSC */
u8 rsvd;
};
struct bfi_rport_delete_req_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 fw_handle; /* firmware rport handle */
u16 rsvd;
};
struct bfi_rport_delete_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 bfa_handle; /* host rport handle */
u8 status; /* rport deletion status */
u8 rsvd;
};
struct bfi_rport_qos_scn_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 bfa_handle; /* host rport handle */
u16 rsvd;
struct bfa_rport_qos_attr_s old_qos_attr; /* Old QoS Attributes */
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;
struct bfi_rport_delete_req_s *delete_req;
struct bfi_rport_speed_req_s *speed_req;
};
union bfi_rport_i2h_msg_u {
struct bfi_msg_s *msg;
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_itn_h2i {
BFI_ITN_H2I_CREATE_REQ = 1, /* i-t nexus creation */
BFI_ITN_H2I_DELETE_REQ = 2, /* i-t nexus deletion */
};
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_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_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_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_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_itn_sler_event_s {
struct bfi_mhdr_s mh; /* common msg header */
u16 bfa_handle; /* bfa handle for itnim */
u16 rsvd;
};
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_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;
};
/*
* Initiator mode IO interface defines.
*/
enum bfi_ioim_h2i {
BFI_IOIM_H2I_IOABORT_REQ = 1, /* IO abort request */
BFI_IOIM_H2I_IOCLEANUP_REQ = 2, /* IO cleanup request */
};
enum bfi_ioim_i2h {
BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1), /* non-fp IO response */
BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2), /* ABORT rsp */
};
/*
* IO command DIF info
*/
struct bfi_ioim_dif_s {
u32 dif_info[4];
};
/*
* FCP IO messages overview
*
* @note
* - Max CDB length supported is 64 bytes.
* - SCSI Linked commands and SCSI bi-directional Commands not
* supported.
*
*/
struct bfi_ioim_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
__be16 io_tag; /* I/O tag */
u16 rport_hdl; /* itnim/rport firmware handle */
struct fcp_cmnd_s cmnd; /* IO request info */
/*
* SG elements array within the IO request must be double word
* aligned. This aligment is required to optimize SGM setup for the IO.
*/
struct bfi_sge_s sges[BFI_SGE_INLINE_MAX];
u8 io_timeout;
u8 dif_en;
u8 rsvd_a[2];
struct bfi_ioim_dif_s dif;
};
/*
* This table shows various IO status codes from firmware and their
* meaning. Host driver can use these status codes to further process
* IO completions.
*
* BFI_IOIM_STS_OK : IO completed with error free SCSI &
* transport status.
* io-tag can be reused.
*
* BFA_IOIM_STS_SCSI_ERR : IO completed with scsi error.
* - io-tag can be reused.
*
* BFI_IOIM_STS_HOST_ABORTED : IO was aborted successfully due to
* host request.
* - io-tag cannot be reused yet.
*
* BFI_IOIM_STS_ABORTED : IO was aborted successfully
* internally by f/w.
* - io-tag cannot be reused yet.
*
* BFI_IOIM_STS_TIMEDOUT : IO timedout and ABTS/RRQ is happening
* in the firmware and
* - io-tag cannot be reused yet.
*
* BFI_IOIM_STS_SQER_NEEDED : Firmware could not recover the IO
* with sequence level error
* logic and hence host needs to retry
* this IO with a different IO tag
* - io-tag cannot be used yet.
*
* BFI_IOIM_STS_NEXUS_ABORT : Second Level Error Recovery from host
* is required because 2 consecutive ABTS
* timedout and host needs logout and
* re-login with the target
* - io-tag cannot be used yet.
*
* BFI_IOIM_STS_UNDERRUN : IO completed with SCSI status good,
* but the data tranferred is less than
* the fcp data length in the command.
* ex. SCSI INQUIRY where transferred
* data length and residue count in FCP
* response accounts for total fcp-dl
* - io-tag can be reused.
*
* BFI_IOIM_STS_OVERRUN : IO completed with SCSI status good,
* but the data transerred is more than
* fcp data length in the command. ex.
* TAPE IOs where blocks can of unequal
* lengths.
* - io-tag can be reused.
*
* BFI_IOIM_STS_RES_FREE : Firmware has completed using io-tag
* during abort process
* - io-tag can be reused.
*
* BFI_IOIM_STS_PROTO_ERR : Firmware detected a protocol error.
* ex target sent more data than
* requested, or there was data frame
* loss and other reasons
* - io-tag cannot be used yet.
*
* BFI_IOIM_STS_DIF_ERR : Firwmare detected DIF error. ex: DIF
* CRC err or Ref Tag err or App tag err.
* - io-tag can be reused.
*
* BFA_IOIM_STS_TSK_MGT_ABORT : IO was aborted because of Task
* Management command from the host
* - io-tag can be reused.
*
* BFI_IOIM_STS_UTAG : Firmware does not know about this
* io_tag.
* - io-tag can be reused.
*/
enum bfi_ioim_status {
BFI_IOIM_STS_OK = 0,
BFI_IOIM_STS_HOST_ABORTED = 1,
BFI_IOIM_STS_ABORTED = 2,
BFI_IOIM_STS_TIMEDOUT = 3,
BFI_IOIM_STS_RES_FREE = 4,
BFI_IOIM_STS_SQER_NEEDED = 5,
BFI_IOIM_STS_PROTO_ERR = 6,
BFI_IOIM_STS_UTAG = 7,
BFI_IOIM_STS_PATHTOV = 8,
};
/*
* I/O response message
*/
struct bfi_ioim_rsp_s {
struct bfi_mhdr_s mh; /* common msg header */
__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 */
u16 abort_tag; /* host abort request tag */
u8 scsi_status; /* scsi status from target */
u8 sns_len; /* scsi sense length */
u8 resid_flags; /* IO residue flags */
u8 rsvd_a;
__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 */
__be16 io_tag; /* I/O tag */
u16 abort_tag; /* unique request tag */
};
/*
* Initiator mode task management command interface defines.
*/
enum bfi_tskim_h2i {
BFI_TSKIM_H2I_TM_REQ = 1, /* task-mgmt command */
BFI_TSKIM_H2I_ABORT_REQ = 2, /* task-mgmt command */
};
enum bfi_tskim_i2h {
BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
};
struct bfi_tskim_req_s {
struct bfi_mhdr_s mh; /* Common msg header */
__be16 tsk_tag; /* task management tag */
u16 itn_fhdl; /* itn firmware handle */
struct scsi_lun lun; /* LU number */
u8 tm_flags; /* see enum fcp_tm_cmnd */
u8 t_secs; /* Timeout value in seconds */
u8 rsvd[2];
};
struct bfi_tskim_abortreq_s {
struct bfi_mhdr_s mh; /* Common msg header */
__be16 tsk_tag; /* task management tag */
u16 rsvd;
};
enum bfi_tskim_status {
/*
* Following are FCP-4 spec defined status codes,
* **DO NOT CHANGE THEM **
*/
BFI_TSKIM_STS_OK = 0,
BFI_TSKIM_STS_NOT_SUPP = 4,
BFI_TSKIM_STS_FAILED = 5,
/*
* Defined by BFA
*/
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 */
__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__ */

459
drivers/scsi/bfa/bfi_reg.h Normal file
View file

@ -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__ */