diff options
Diffstat (limited to 'drivers/scsi/bfa/bfa_ioc.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.c | 762 |
1 files changed, 234 insertions, 528 deletions
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 397d7e9eade5..e038bc9769f6 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -18,7 +18,7 @@ #include <bfa.h> #include <bfa_ioc.h> #include <bfa_fwimg_priv.h> -#include <bfa_trcmod_priv.h> +#include <cna/bfa_cna_trcmod.h> #include <cs/bfa_debug.h> #include <bfi/bfi_ioc.h> #include <bfi/bfi_ctreg.h> @@ -27,18 +27,17 @@ #include <log/bfa_log_hal.h> #include <defs/bfa_defs_pci.h> -BFA_TRC_FILE(HAL, IOC); +BFA_TRC_FILE(CNA, IOC); /** * IOC local definitions */ #define BFA_IOC_TOV 2000 /* msecs */ -#define BFA_IOC_HB_TOV 1000 /* msecs */ -#define BFA_IOC_HB_FAIL_MAX 4 -#define BFA_IOC_HWINIT_MAX 2 +#define BFA_IOC_HWSEM_TOV 500 /* msecs */ +#define BFA_IOC_HB_TOV 500 /* msecs */ +#define BFA_IOC_HWINIT_MAX 2 #define BFA_IOC_FWIMG_MINSZ (16 * 1024) -#define BFA_IOC_TOV_RECOVER (BFA_IOC_HB_FAIL_MAX * BFA_IOC_HB_TOV \ - + BFA_IOC_TOV) +#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV #define bfa_ioc_timer_start(__ioc) \ bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \ @@ -51,12 +50,25 @@ BFA_TRC_FILE(HAL, IOC); (sizeof(struct bfa_trc_mod_s) - \ BFA_TRC_MAX * sizeof(struct bfa_trc_s))) #define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn)) -#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++) -#define BFA_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS) -#define BFA_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) -#define BFA_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) -bfa_boolean_t bfa_auto_recover = BFA_FALSE; +/** + * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. + */ + +#define bfa_ioc_firmware_lock(__ioc) \ + ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc)) +#define bfa_ioc_firmware_unlock(__ioc) \ + ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc)) +#define bfa_ioc_fwimg_get_chunk(__ioc, __off) \ + ((__ioc)->ioc_hwif->ioc_fwimg_get_chunk(__ioc, __off)) +#define bfa_ioc_fwimg_get_size(__ioc) \ + ((__ioc)->ioc_hwif->ioc_fwimg_get_size(__ioc)) +#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc)) +#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) +#define bfa_ioc_notify_hbfail(__ioc) \ + ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc)) + +bfa_boolean_t bfa_auto_recover = BFA_TRUE; /* * forward declarations @@ -64,7 +76,6 @@ bfa_boolean_t bfa_auto_recover = BFA_FALSE; static void bfa_ioc_aen_post(struct bfa_ioc_s *bfa, enum bfa_ioc_aen_event event); static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc); -static void bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc); static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc); static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force); static void bfa_ioc_timeout(void *ioc); @@ -77,8 +88,6 @@ static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force); static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc); static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc); static void bfa_ioc_recover(struct bfa_ioc_s *ioc); -static bfa_boolean_t bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc); -static void bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc); static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); @@ -508,14 +517,19 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_trc(ioc, event); switch (event) { - case IOC_E_HWERROR: case IOC_E_FWRSP_DISABLE: bfa_ioc_timer_stop(ioc); + bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); + break; + + case IOC_E_HWERROR: + bfa_ioc_timer_stop(ioc); /* * !!! fall through !!! */ case IOC_E_TIMEOUT: + bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL); bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); break; @@ -608,15 +622,12 @@ bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc) * Mark IOC as failed in hardware and stop firmware. */ bfa_ioc_lpu_stop(ioc); - bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_HBFAIL); + bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL); - if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) { - bfa_reg_write(ioc->ioc_regs.ll_halt, __FW_INIT_HALT_P); - /* - * Wait for halt to take effect - */ - bfa_reg_read(ioc->ioc_regs.ll_halt); - } + /** + * Notify other functions on HB failure. + */ + bfa_ioc_notify_hbfail(ioc); /** * Notify driver and common modules registered for notification. @@ -672,6 +683,12 @@ bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event) */ break; + case IOC_E_HWERROR: + /* + * HB failure notification, ignore. + */ + break; + default: bfa_sm_fault(ioc, event); } @@ -700,7 +717,7 @@ bfa_ioc_disable_comp(struct bfa_ioc_s *ioc) } } -static void +void bfa_ioc_sem_timeout(void *ioc_arg) { struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg; @@ -708,26 +725,32 @@ bfa_ioc_sem_timeout(void *ioc_arg) bfa_ioc_hw_sem_get(ioc); } -static void -bfa_ioc_usage_sem_get(struct bfa_ioc_s *ioc) +bfa_boolean_t +bfa_ioc_sem_get(bfa_os_addr_t sem_reg) { - u32 r32; - int cnt = 0; -#define BFA_SEM_SPINCNT 1000 + u32 r32; + int cnt = 0; +#define BFA_SEM_SPINCNT 3000 - do { - r32 = bfa_reg_read(ioc->ioc_regs.ioc_usage_sem_reg); + r32 = bfa_reg_read(sem_reg); + + while (r32 && (cnt < BFA_SEM_SPINCNT)) { cnt++; - if (cnt > BFA_SEM_SPINCNT) - break; - } while (r32 != 0); + bfa_os_udelay(2); + r32 = bfa_reg_read(sem_reg); + } + + if (r32 == 0) + return BFA_TRUE; + bfa_assert(cnt < BFA_SEM_SPINCNT); + return BFA_FALSE; } -static void -bfa_ioc_usage_sem_release(struct bfa_ioc_s *ioc) +void +bfa_ioc_sem_release(bfa_os_addr_t sem_reg) { - bfa_reg_write(ioc->ioc_regs.ioc_usage_sem_reg, 1); + bfa_reg_write(sem_reg, 1); } static void @@ -737,7 +760,7 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc) /** * First read to the semaphore register will return 0, subsequent reads - * will return 1. Semaphore is released by writing 0 to the register + * will return 1. Semaphore is released by writing 1 to the register */ r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg); if (r32 == 0) { @@ -746,10 +769,10 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc) } bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout, - ioc, BFA_IOC_TOV); + ioc, BFA_IOC_HWSEM_TOV); } -static void +void bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc) { bfa_reg_write(ioc->ioc_regs.ioc_sem_reg, 1); @@ -828,7 +851,7 @@ bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc) /** * Get driver and firmware versions. */ -static void +void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) { u32 pgnum, pgoff; @@ -847,24 +870,10 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) } } -static u32 * -bfa_ioc_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off) -{ - if (ioc->ctdev) - return bfi_image_ct_get_chunk(off); - return bfi_image_cb_get_chunk(off); -} - -static u32 -bfa_ioc_fwimg_get_size(struct bfa_ioc_s *ioc) -{ -return (ioc->ctdev) ? bfi_image_ct_size : bfi_image_cb_size; -} - /** * Returns TRUE if same. */ -static bfa_boolean_t +bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) { struct bfi_ioc_image_hdr_s *drv_fwhdr; @@ -921,95 +930,6 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc) } /** - * Return true if firmware of current driver matches the running firmware. - */ -static bfa_boolean_t -bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc) -{ - enum bfi_ioc_state ioc_fwstate; - u32 usecnt; - struct bfi_ioc_image_hdr_s fwhdr; - - /** - * Firmware match check is relevant only for CNA. - */ - if (!ioc->cna) - return BFA_TRUE; - - /** - * If bios boot (flash based) -- do not increment usage count - */ - if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) - return BFA_TRUE; - - bfa_ioc_usage_sem_get(ioc); - usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg); - - /** - * If usage count is 0, always return TRUE. - */ - if (usecnt == 0) { - bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 1); - bfa_ioc_usage_sem_release(ioc); - bfa_trc(ioc, usecnt); - return BFA_TRUE; - } - - ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate); - bfa_trc(ioc, ioc_fwstate); - - /** - * Use count cannot be non-zero and chip in uninitialized state. - */ - bfa_assert(ioc_fwstate != BFI_IOC_UNINIT); - - /** - * Check if another driver with a different firmware is active - */ - bfa_ioc_fwver_get(ioc, &fwhdr); - if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { - bfa_ioc_usage_sem_release(ioc); - bfa_trc(ioc, usecnt); - return BFA_FALSE; - } - - /** - * Same firmware version. Increment the reference count. - */ - usecnt++; - bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt); - bfa_ioc_usage_sem_release(ioc); - bfa_trc(ioc, usecnt); - return BFA_TRUE; -} - -static void -bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc) -{ - u32 usecnt; - - /** - * Firmware lock is relevant only for CNA. - * If bios boot (flash based) -- do not decrement usage count - */ - if (!ioc->cna || (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)) - return; - - /** - * decrement usage count - */ - bfa_ioc_usage_sem_get(ioc); - usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg); - bfa_assert(usecnt > 0); - - usecnt--; - bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt); - bfa_trc(ioc, usecnt); - - bfa_ioc_usage_sem_release(ioc); -} - -/** * Conditionally flush any pending message from firmware at start. */ static void @@ -1152,33 +1072,27 @@ bfa_ioc_send_getattr(struct bfa_ioc_s *ioc) static void bfa_ioc_hb_check(void *cbarg) { - struct bfa_ioc_s *ioc = cbarg; - u32 hb_count; + struct bfa_ioc_s *ioc = cbarg; + u32 hb_count; hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat); if (ioc->hb_count == hb_count) { - ioc->hb_fail++; - } else { - ioc->hb_count = hb_count; - ioc->hb_fail = 0; - } - - if (ioc->hb_fail >= BFA_IOC_HB_FAIL_MAX) { - bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE, hb_count); - ioc->hb_fail = 0; + bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE, + hb_count); bfa_ioc_recover(ioc); return; + } else { + ioc->hb_count = hb_count; } bfa_ioc_mbox_poll(ioc); - bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc, - BFA_IOC_HB_TOV); + bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, + ioc, BFA_IOC_HB_TOV); } static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc) { - ioc->hb_fail = 0; ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat); bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc, BFA_IOC_HB_TOV); @@ -1191,112 +1105,6 @@ bfa_ioc_hb_stop(struct bfa_ioc_s *ioc) } /** - * 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}, { - 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; -} iocreg_mbcmd_p0[] = { - { - HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT}, { - HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT}, { - HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT}, { - HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT} -}; - -/** - * Host <-> LPU mailbox command/status registers - port 1 - */ -static struct { - u32 hfn, lpu; -} iocreg_mbcmd_p1[] = { - { - HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT}, { - HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT}, { - HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT}, { - HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT} -}; - -/** - * Shared IRQ handling in INTX mode - */ -static struct { - u32 isr, msk; -} iocreg_shirq_next[] = { - { - HOSTFN1_INT_STATUS, HOSTFN1_INT_MSK}, { - HOSTFN2_INT_STATUS, HOSTFN2_INT_MSK}, { - HOSTFN3_INT_STATUS, HOSTFN3_INT_MSK}, { -HOSTFN0_INT_STATUS, HOSTFN0_INT_MSK},}; - -static void -bfa_ioc_reg_init(struct bfa_ioc_s *ioc) -{ - bfa_os_addr_t 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.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; - ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; - ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; - } else { - ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); - ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); - ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; - ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; - ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; - } - - /** - * Shared IRQ handling in INTX mode - */ - ioc->ioc_regs.shirq_isr_next = rb + iocreg_shirq_next[pcifn].isr; - ioc->ioc_regs.shirq_msk_next = rb + iocreg_shirq_next[pcifn].msk; - - /* - * PSS control registers - */ - ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); - ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG); - ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG); - - /* - * IOC 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_usage_reg = (rb + BFA_FW_USE_COUNT); - - /** - * sram memory access - */ - ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); - ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB; - if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) - ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; -} - -/** * Initiate a full firmware download. */ static void @@ -1321,9 +1129,6 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) boot_type = BFI_BOOT_TYPE_FLASH; fwimg = bfa_ioc_fwimg_get_chunk(ioc, chunkno); - fwimg[BFI_BOOT_TYPE_OFF / sizeof(u32)] = bfa_os_swap32(boot_type); - fwimg[BFI_BOOT_PARAM_OFF / sizeof(u32)] = - bfa_os_swap32(boot_param); pgnum = bfa_ioc_smem_pgnum(ioc, loff); pgoff = bfa_ioc_smem_pgoff(ioc, loff); @@ -1332,17 +1137,17 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, for (i = 0; i < bfa_ioc_fwimg_get_size(ioc); i++) { - if (BFA_FLASH_CHUNK_NO(i) != chunkno) { - chunkno = BFA_FLASH_CHUNK_NO(i); + if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) { + chunkno = BFA_IOC_FLASH_CHUNK_NO(i); fwimg = bfa_ioc_fwimg_get_chunk(ioc, - BFA_FLASH_CHUNK_ADDR(chunkno)); + BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); } /** * write smem */ bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, - fwimg[BFA_FLASH_OFFSET_IN_CHUNK(i)]); + fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]); loff += sizeof(u32); @@ -1358,6 +1163,14 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, bfa_reg_write(ioc->ioc_regs.host_page_num_fn, bfa_ioc_smem_pgnum(ioc, 0)); + + /* + * Set boot type and boot param at the end. + */ + bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF, + bfa_os_swap32(boot_type)); + bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_PARAM_OFF, + bfa_os_swap32(boot_param)); } static void @@ -1440,168 +1253,10 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc) } /** - * Initialize IOC to port mapping. - */ - -#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) -static void -bfa_ioc_map_port(struct bfa_ioc_s *ioc) -{ - bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; - u32 r32; - - /** - * For crossbow, port id is same as pci function. - */ - if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT) { - ioc->port_id = bfa_ioc_pcifn(ioc); - return; - } - - /** - * For catapult, base port id on personality register and IOC type - */ - r32 = bfa_reg_read(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); -} - - - -/** * bfa_ioc_public */ /** -* Set interrupt mode for a function: INTX or MSIX - */ -void -bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) -{ - bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; - u32 r32, mode; - - r32 = bfa_reg_read(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) - 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); - - bfa_reg_write(rb + FNC_PERS_REG, r32); -} - -bfa_status_t -bfa_ioc_pll_init(struct bfa_ioc_s *ioc) -{ - bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; - u32 pll_sclk, pll_fclk, r32; - - if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) { - pll_sclk = - __APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN | - __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(0U) | - __APP_PLL_312_JITLMT0_1(3U) | - __APP_PLL_312_CNTLMT0_1(1U); - pll_fclk = - __APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN | - __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(0U) | - __APP_PLL_425_JITLMT0_1(3U) | - __APP_PLL_425_CNTLMT0_1(1U); - - /** - * For catapult, choose operational mode FC/FCoE - */ - if (ioc->fcmode) { - bfa_reg_write((rb + OP_MODE), 0); - bfa_reg_write((rb + ETH_MAC_SER_REG), - __APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 - | __APP_EMS_CHANNEL_SEL); - } else { - ioc->pllinit = BFA_TRUE; - bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE); - bfa_reg_write((rb + ETH_MAC_SER_REG), - __APP_EMS_REFCKBUFEN1); - } - } else { - pll_sclk = - __APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN | - __APP_PLL_312_P0_1(3U) | __APP_PLL_312_JITLMT0_1(3U) | - __APP_PLL_312_CNTLMT0_1(3U); - pll_fclk = - __APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN | - __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) | - __APP_PLL_425_JITLMT0_1(3U) | - __APP_PLL_425_CNTLMT0_1(3U); - } - - bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT); - bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT); - - bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); - bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); - bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); - bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); - bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); - bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); - - bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, - __APP_PLL_312_LOGIC_SOFT_RESET); - bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, - __APP_PLL_312_BYPASS | __APP_PLL_312_LOGIC_SOFT_RESET); - bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, - __APP_PLL_425_LOGIC_SOFT_RESET); - bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, - __APP_PLL_425_BYPASS | __APP_PLL_425_LOGIC_SOFT_RESET); - bfa_os_udelay(2); - bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, - __APP_PLL_312_LOGIC_SOFT_RESET); - bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, - __APP_PLL_425_LOGIC_SOFT_RESET); - - bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, - pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET); - bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, - pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET); - - /** - * Wait for PLLs to lock. - */ - bfa_os_udelay(2000); - bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); - bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); - - bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk); - bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk); - - if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) { - bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START); - bfa_os_udelay(1000); - r32 = bfa_reg_read((rb + MBIST_STAT_REG)); - bfa_trc(ioc, r32); - } - - return BFA_STATUS_OK; -} - -/** * Interface used by diag module to do firmware boot with memory test * as the entry vector. */ @@ -1642,7 +1297,7 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param) void bfa_ioc_auto_recover(bfa_boolean_t auto_recover) { - bfa_auto_recover = BFA_FALSE; + bfa_auto_recover = auto_recover; } @@ -1764,6 +1419,14 @@ bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, ioc->ctdev = (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT); ioc->cna = ioc->ctdev && !ioc->fcmode; + /** + * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c + */ + if (ioc->ctdev) + bfa_ioc_set_ct_hwif(ioc); + else + bfa_ioc_set_cb_hwif(ioc); + bfa_ioc_map_port(ioc); bfa_ioc_reg_init(ioc); } @@ -1830,7 +1493,6 @@ return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0; void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave) { - bfa_assert(ioc->auto_recover); ioc->dbg_fwsave = dbg_fwsave; ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover); } @@ -1973,7 +1635,7 @@ bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc) ((__sm) == BFI_IOC_INITING) || \ ((__sm) == BFI_IOC_HWINIT) || \ ((__sm) == BFI_IOC_DISABLED) || \ - ((__sm) == BFI_IOC_HBFAIL) || \ + ((__sm) == BFI_IOC_FAIL) || \ ((__sm) == BFI_IOC_CFG_DISABLED)) /** @@ -2017,46 +1679,28 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, struct bfa_adapter_attr_s *ad_attr) { struct bfi_ioc_attr_s *ioc_attr; - char model[BFA_ADAPTER_MODEL_NAME_LEN]; ioc_attr = ioc->attr; - bfa_os_memcpy((void *)&ad_attr->serial_num, - (void *)ioc_attr->brcd_serialnum, - BFA_ADAPTER_SERIAL_NUM_LEN); - - bfa_os_memcpy(&ad_attr->fw_ver, ioc_attr->fw_version, BFA_VERSION_LEN); - bfa_os_memcpy(&ad_attr->optrom_ver, ioc_attr->optrom_version, - BFA_VERSION_LEN); - bfa_os_memcpy(&ad_attr->manufacturer, BFA_MFG_NAME, - BFA_ADAPTER_MFG_NAME_LEN); + + bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num); + bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver); + bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver); + bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer); bfa_os_memcpy(&ad_attr->vpd, &ioc_attr->vpd, sizeof(struct bfa_mfg_vpd_s)); - ad_attr->nports = BFI_ADAPTER_GETP(NPORTS, ioc_attr->adapter_prop); - ad_attr->max_speed = BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop); + ad_attr->nports = bfa_ioc_get_nports(ioc); + ad_attr->max_speed = bfa_ioc_speed_sup(ioc); - /** - * model name - */ - if (BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop) == 10) { - strcpy(model, "BR-10?0"); - model[5] = '0' + ad_attr->nports; - } else { - strcpy(model, "Brocade-??5"); - model[8] = - '0' + BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop); - model[9] = '0' + ad_attr->nports; - } + bfa_ioc_get_adapter_model(ioc, ad_attr->model); + /* For now, model descr uses same model string */ + bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr); if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop)) ad_attr->prototype = 1; else ad_attr->prototype = 0; - bfa_os_memcpy(&ad_attr->model, model, BFA_ADAPTER_MODEL_NAME_LEN); - bfa_os_memcpy(&ad_attr->model_descr, &ad_attr->model, - BFA_ADAPTER_MODEL_NAME_LEN); - ad_attr->pwwn = bfa_ioc_get_pwwn(ioc); ad_attr->mac = bfa_ioc_get_mac(ioc); @@ -2064,41 +1708,122 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, ad_attr->pcie_lanes = ioc_attr->pcie_lanes; ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig; ad_attr->asic_rev = ioc_attr->asic_rev; - ad_attr->hw_ver[0] = 'R'; - ad_attr->hw_ver[1] = 'e'; - ad_attr->hw_ver[2] = 'v'; - ad_attr->hw_ver[3] = '-'; - ad_attr->hw_ver[4] = ioc_attr->asic_rev; - ad_attr->hw_ver[5] = '\0'; + + bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); ad_attr->cna_capable = ioc->cna; } +enum bfa_ioc_type_e +bfa_ioc_get_type(struct bfa_ioc_s *ioc) +{ + if (!ioc->ctdev || ioc->fcmode) + return BFA_IOC_TYPE_FC; + else if (ioc->ioc_mc == BFI_MC_IOCFC) + return BFA_IOC_TYPE_FCoE; + else if (ioc->ioc_mc == BFI_MC_LL) + return BFA_IOC_TYPE_LL; + else { + bfa_assert(ioc->ioc_mc == BFI_MC_LL); + return BFA_IOC_TYPE_LL; + } +} + +void +bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num) +{ + bfa_os_memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN); + bfa_os_memcpy((void *)serial_num, + (void *)ioc->attr->brcd_serialnum, + BFA_ADAPTER_SERIAL_NUM_LEN); +} + +void +bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver) +{ + bfa_os_memset((void *)fw_ver, 0, BFA_VERSION_LEN); + bfa_os_memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN); +} + +void +bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev) +{ + bfa_assert(chip_rev); + + bfa_os_memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN); + + chip_rev[0] = 'R'; + chip_rev[1] = 'e'; + chip_rev[2] = 'v'; + chip_rev[3] = '-'; + chip_rev[4] = ioc->attr->asic_rev; + chip_rev[5] = '\0'; +} + +void +bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver) +{ + bfa_os_memset((void *)optrom_ver, 0, BFA_VERSION_LEN); + bfa_os_memcpy(optrom_ver, ioc->attr->optrom_version, + BFA_VERSION_LEN); +} + +void +bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer) +{ + bfa_os_memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN); + bfa_os_memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); +} + +void +bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model) +{ + struct bfi_ioc_attr_s *ioc_attr; + u8 nports; + u8 max_speed; + + bfa_assert(model); + bfa_os_memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN); + + ioc_attr = ioc->attr; + + nports = bfa_ioc_get_nports(ioc); + max_speed = bfa_ioc_speed_sup(ioc); + + /** + * model name + */ + if (max_speed == 10) { + strcpy(model, "BR-10?0"); + model[5] = '0' + nports; + } else { + strcpy(model, "Brocade-??5"); + model[8] = '0' + max_speed; + model[9] = '0' + nports; + } +} + +enum bfa_ioc_state +bfa_ioc_get_state(struct bfa_ioc_s *ioc) +{ + return bfa_sm_to_state(ioc_sm_table, ioc->fsm); +} + void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr) { bfa_os_memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s)); - ioc_attr->state = bfa_sm_to_state(ioc_sm_table, ioc->fsm); + ioc_attr->state = bfa_ioc_get_state(ioc); ioc_attr->port_id = ioc->port_id; - if (!ioc->ctdev) - ioc_attr->ioc_type = BFA_IOC_TYPE_FC; - else if (ioc->ioc_mc == BFI_MC_IOCFC) - ioc_attr->ioc_type = BFA_IOC_TYPE_FCoE; - else if (ioc->ioc_mc == BFI_MC_LL) - ioc_attr->ioc_type = BFA_IOC_TYPE_LL; + ioc_attr->ioc_type = bfa_ioc_get_type(ioc); bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr); ioc_attr->pci_attr.device_id = ioc->pcidev.device_id; ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func; - ioc_attr->pci_attr.chip_rev[0] = 'R'; - ioc_attr->pci_attr.chip_rev[1] = 'e'; - ioc_attr->pci_attr.chip_rev[2] = 'v'; - ioc_attr->pci_attr.chip_rev[3] = '-'; - ioc_attr->pci_attr.chip_rev[4] = ioc_attr->adapter_attr.asic_rev; - ioc_attr->pci_attr.chip_rev[5] = '\0'; + bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev); } /** @@ -2195,29 +1920,6 @@ bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc) } /** - * Return true if interrupt should be claimed. - */ -bfa_boolean_t -bfa_ioc_intx_claim(struct bfa_ioc_s *ioc) -{ - u32 isr, msk; - - /** - * Always claim if not catapult. - */ - if (!ioc->ctdev) - return BFA_TRUE; - - /** - * FALSE if next device is claiming interrupt. - * TRUE if next device is not interrupting or not present. - */ - msk = bfa_reg_read(ioc->ioc_regs.shirq_msk_next); - isr = bfa_reg_read(ioc->ioc_regs.shirq_isr_next); - return !(isr & ~msk); -} - -/** * Send AEN notification */ static void @@ -2226,32 +1928,14 @@ bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event) union bfa_aen_data_u aen_data; struct bfa_log_mod_s *logmod = ioc->logm; s32 inst_num = 0; - struct bfa_ioc_attr_s ioc_attr; + enum bfa_ioc_type_e ioc_type; - switch (event) { - case BFA_IOC_AEN_HBGOOD: - bfa_log(logmod, BFA_AEN_IOC_HBGOOD, inst_num); - break; - case BFA_IOC_AEN_HBFAIL: - bfa_log(logmod, BFA_AEN_IOC_HBFAIL, inst_num); - break; - case BFA_IOC_AEN_ENABLE: - bfa_log(logmod, BFA_AEN_IOC_ENABLE, inst_num); - break; - case BFA_IOC_AEN_DISABLE: - bfa_log(logmod, BFA_AEN_IOC_DISABLE, inst_num); - break; - case BFA_IOC_AEN_FWMISMATCH: - bfa_log(logmod, BFA_AEN_IOC_FWMISMATCH, inst_num); - break; - default: - break; - } + bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, event), inst_num); memset(&aen_data.ioc.pwwn, 0, sizeof(aen_data.ioc.pwwn)); memset(&aen_data.ioc.mac, 0, sizeof(aen_data.ioc.mac)); - bfa_ioc_get_attr(ioc, &ioc_attr); - switch (ioc_attr.ioc_type) { + ioc_type = bfa_ioc_get_type(ioc); + switch (ioc_type) { case BFA_IOC_TYPE_FC: aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc); break; @@ -2263,10 +1947,10 @@ bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event) aen_data.ioc.mac = bfa_ioc_get_mac(ioc); break; default: - bfa_assert(ioc_attr.ioc_type == BFA_IOC_TYPE_FC); + bfa_assert(ioc_type == BFA_IOC_TYPE_FC); break; } - aen_data.ioc.ioc_type = ioc_attr.ioc_type; + aen_data.ioc.ioc_type = ioc_type; } /** @@ -2290,6 +1974,15 @@ bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen) } /** + * Clear saved firmware trace + */ +void +bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc) +{ + ioc->dbg_fwsave_once = BFA_TRUE; +} + +/** * Retrieve saved firmware trace from a prior IOC failure. */ bfa_status_t @@ -2304,6 +1997,13 @@ bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen) pgnum = bfa_ioc_smem_pgnum(ioc, loff); loff = bfa_ioc_smem_pgoff(ioc, loff); + + /* + * Hold semaphore to serialize pll init and fwtrc. + */ + if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) + return BFA_STATUS_FAILED; + bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum); tlen = *trclen; @@ -2329,6 +2029,12 @@ bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen) } bfa_reg_write(ioc->ioc_regs.host_page_num_fn, bfa_ioc_smem_pgnum(ioc, 0)); + + /* + * release semaphore. + */ + bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); + bfa_trc(ioc, pgnum); *trclen = tlen * sizeof(u32); |