[SCSI] bfa: Replace bfa_get_attr() with specific APIs
[safe/jmp/linux-2.6] / drivers / scsi / bfa / bfa_ioc.c
index 1493489..e038bc9 100644 (file)
@@ -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>
 #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);
 }
@@ -1953,8 +1615,8 @@ bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
 bfa_boolean_t
 bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
 {
-       return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
-               || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled));
+       return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
+               || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
 }
 
 /**
@@ -1963,9 +1625,9 @@ bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
 bfa_boolean_t
 bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
 {
-       return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
+       return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
                || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
-               || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch));
+               || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
 }
 
 #define bfa_ioc_state_disabled(__sm)           \
@@ -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);