[SCSI] bfa: Update RME interrupt handling.
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / bfa / bfa_core.c
index 0048fc8646b44a514cdbf18627128e772938abc7..0c236964c67e26ac42598ddc9bb091e2d312bc1e 100644 (file)
@@ -25,6 +25,7 @@ BFA_TRC_FILE(HAL, CORE);
  * BFA module list terminated by NULL
  */
 static struct bfa_module_s *hal_mods[] = {
+       &hal_mod_fcdiag,
        &hal_mod_sgpg,
        &hal_mod_fcport,
        &hal_mod_fcxp,
@@ -41,7 +42,7 @@ static struct bfa_module_s *hal_mods[] = {
 static bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
        bfa_isr_unhandled,      /* NONE */
        bfa_isr_unhandled,      /* BFI_MC_IOC */
-       bfa_isr_unhandled,      /* BFI_MC_DIAG */
+       bfa_fcdiag_intr,        /* BFI_MC_DIAG */
        bfa_isr_unhandled,      /* BFI_MC_FLASH */
        bfa_isr_unhandled,      /* BFI_MC_CEE */
        bfa_fcport_isr,         /* BFI_MC_FCPORT */
@@ -89,46 +90,78 @@ static bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
 
 
 static void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+bfa_com_port_attach(struct bfa_s *bfa)
 {
        struct bfa_port_s       *port = &bfa->modules.port;
-       u32                     dm_len;
-       u8                      *dm_kva;
-       u64                     dm_pa;
+       struct bfa_mem_dma_s    *port_dma = BFA_MEM_PORT_DMA(bfa);
 
-       dm_len = bfa_port_meminfo();
-       dm_kva = bfa_meminfo_dma_virt(mi);
-       dm_pa  = bfa_meminfo_dma_phys(mi);
-
-       memset(port, 0, sizeof(struct bfa_port_s));
        bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
-       bfa_port_mem_claim(port, dm_kva, dm_pa);
-
-       bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
-       bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+       bfa_port_mem_claim(port, port_dma->kva_curp, port_dma->dma_curp);
 }
 
 /*
  * ablk module attach
  */
 static void
-bfa_com_ablk_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+bfa_com_ablk_attach(struct bfa_s *bfa)
 {
        struct bfa_ablk_s       *ablk = &bfa->modules.ablk;
-       u32                     dm_len;
-       u8                      *dm_kva;
-       u64                     dm_pa;
+       struct bfa_mem_dma_s    *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
 
-       dm_len = bfa_ablk_meminfo();
-       dm_kva = bfa_meminfo_dma_virt(mi);
-       dm_pa  = bfa_meminfo_dma_phys(mi);
-
-       memset(ablk, 0, sizeof(struct bfa_ablk_s));
        bfa_ablk_attach(ablk, &bfa->ioc);
-       bfa_ablk_memclaim(ablk, dm_kva, dm_pa);
+       bfa_ablk_memclaim(ablk, ablk_dma->kva_curp, ablk_dma->dma_curp);
+}
+
+static void
+bfa_com_cee_attach(struct bfa_s *bfa)
+{
+       struct bfa_cee_s        *cee = &bfa->modules.cee;
+       struct bfa_mem_dma_s    *cee_dma = BFA_MEM_CEE_DMA(bfa);
 
-       bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
-       bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+       cee->trcmod = bfa->trcmod;
+       bfa_cee_attach(cee, &bfa->ioc, bfa);
+       bfa_cee_mem_claim(cee, cee_dma->kva_curp, cee_dma->dma_curp);
+}
+
+static void
+bfa_com_sfp_attach(struct bfa_s *bfa)
+{
+       struct bfa_sfp_s        *sfp = BFA_SFP_MOD(bfa);
+       struct bfa_mem_dma_s    *sfp_dma = BFA_MEM_SFP_DMA(bfa);
+
+       bfa_sfp_attach(sfp, &bfa->ioc, bfa, bfa->trcmod);
+       bfa_sfp_memclaim(sfp, sfp_dma->kva_curp, sfp_dma->dma_curp);
+}
+
+static void
+bfa_com_flash_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+       struct bfa_flash_s      *flash = BFA_FLASH(bfa);
+       struct bfa_mem_dma_s    *flash_dma = BFA_MEM_FLASH_DMA(bfa);
+
+       bfa_flash_attach(flash, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+       bfa_flash_memclaim(flash, flash_dma->kva_curp,
+                          flash_dma->dma_curp, mincfg);
+}
+
+static void
+bfa_com_diag_attach(struct bfa_s *bfa)
+{
+       struct bfa_diag_s       *diag = BFA_DIAG_MOD(bfa);
+       struct bfa_mem_dma_s    *diag_dma = BFA_MEM_DIAG_DMA(bfa);
+
+       bfa_diag_attach(diag, &bfa->ioc, bfa, bfa_fcport_beacon, bfa->trcmod);
+       bfa_diag_memclaim(diag, diag_dma->kva_curp, diag_dma->dma_curp);
+}
+
+static void
+bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+       struct bfa_phy_s        *phy = BFA_PHY(bfa);
+       struct bfa_mem_dma_s    *phy_dma = BFA_MEM_PHY_DMA(bfa);
+
+       bfa_phy_attach(phy, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+       bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg);
 }
 
 /*
@@ -145,6 +178,7 @@ enum {
        BFA_IOCFC_ACT_INIT      = 1,
        BFA_IOCFC_ACT_STOP      = 2,
        BFA_IOCFC_ACT_DISABLE   = 3,
+       BFA_IOCFC_ACT_ENABLE    = 4,
 };
 
 #define DEF_CFG_NUM_FABRICS            1
@@ -203,8 +237,6 @@ bfa_isr_rspq(struct bfa_s *bfa, int qid)
        u32     pi, ci;
        struct list_head *waitq;
 
-       bfa_isr_rspq_ack(bfa, qid);
-
        ci = bfa_rspq_ci(bfa, qid);
        pi = bfa_rspq_pi(bfa, qid);
 
@@ -217,11 +249,9 @@ bfa_isr_rspq(struct bfa_s *bfa, int qid)
        }
 
        /*
-        * update CI
+        * acknowledge RME completions and update CI
         */
-       bfa_rspq_ci(bfa, qid) = pi;
-       writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
-       mmiowb();
+       bfa_isr_rspq_ack(bfa, qid, ci);
 
        /*
         * Resume any pending requests in the corresponding reqq.
@@ -291,23 +321,19 @@ bfa_intx(struct bfa_s *bfa)
        int queue;
 
        intr = readl(bfa->iocfc.bfa_regs.intr_status);
-       if (!intr)
-               return BFA_FALSE;
 
        qintr = intr & (__HFN_INT_RME_MASK | __HFN_INT_CPE_MASK);
        if (qintr)
                writel(qintr, bfa->iocfc.bfa_regs.intr_status);
 
        /*
-        * RME completion queue interrupt
+        * Unconditional RME completion queue interrupt
         */
-       qintr = intr & __HFN_INT_RME_MASK;
-       if (qintr && bfa->queue_process) {
+       if (bfa->queue_process) {
                for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
                        bfa_isr_rspq(bfa, queue);
        }
 
-       intr &= ~qintr;
        if (!intr)
                return BFA_TRUE;
 
@@ -398,7 +424,8 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
                                   __HFN_INT_MBOX_LPU1_CT2);
                intr    &= __HFN_INT_ERR_MASK_CT2;
        } else {
-               halt_isr = intr & __HFN_INT_LL_HALT;
+               halt_isr = bfa_asic_id_ct(bfa->ioc.pcidev.device_id) ?
+                                         (intr & __HFN_INT_LL_HALT) : 0;
                pss_isr  = intr & __HFN_INT_ERR_PSS;
                lpu_isr  = intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1);
                intr    &= __HFN_INT_ERR_MASK;
@@ -444,41 +471,6 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
  *  BFA IOC private functions
  */
 
-static void
-bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-       int             i, per_reqq_sz, per_rspq_sz;
-
-       per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-                                 BFA_DMA_ALIGN_SZ);
-       per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-                                 BFA_DMA_ALIGN_SZ);
-
-       /*
-        * Calculate CQ size
-        */
-       for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-               *dm_len = *dm_len + per_reqq_sz;
-               *dm_len = *dm_len + per_rspq_sz;
-       }
-
-       /*
-        * Calculate Shadow CI/PI size
-        */
-       for (i = 0; i < cfg->fwcfg.num_cqs; i++)
-               *dm_len += (2 * BFA_CACHELINE_SZ);
-}
-
-static void
-bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-       *dm_len +=
-               BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-       *dm_len +=
-               BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-                           BFA_CACHELINE_SZ);
-}
-
 /*
  * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
  */
@@ -579,7 +571,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        } else {
                iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
                iocfc->hwif.hw_reqq_ack = NULL;
-               iocfc->hwif.hw_rspq_ack = NULL;
+               iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
                iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
                iocfc->hwif.hw_msix_ctrl_install = bfa_hwcb_msix_ctrl_install;
                iocfc->hwif.hw_msix_queue_install = bfa_hwcb_msix_queue_install;
@@ -596,7 +588,7 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        if (bfa_asic_id_ct2(bfa_ioc_devid(&bfa->ioc))) {
                iocfc->hwif.hw_reginit = bfa_hwct2_reginit;
                iocfc->hwif.hw_isr_mode_set = NULL;
-               iocfc->hwif.hw_rspq_ack = NULL;
+               iocfc->hwif.hw_rspq_ack = bfa_hwct2_rspq_ack;
        }
 
        iocfc->hwif.hw_reginit(bfa);
@@ -604,48 +596,42 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 }
 
 static void
-bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
-                   struct bfa_meminfo_s *meminfo)
+bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
 {
-       u8             *dm_kva;
-       u64     dm_pa;
-       int             i, per_reqq_sz, per_rspq_sz;
+       u8      *dm_kva = NULL;
+       u64     dm_pa = 0;
+       int     i, per_reqq_sz, per_rspq_sz, dbgsz;
        struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
-       int             dbgsz;
+       struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
+       struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
+       struct bfa_mem_dma_s *reqq_dma, *rspq_dma;
 
-       dm_kva = bfa_meminfo_dma_virt(meminfo);
-       dm_pa = bfa_meminfo_dma_phys(meminfo);
-
-       /*
-        * First allocate dma memory for IOC.
-        */
-       bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
-       dm_kva += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
-       dm_pa  += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+       /* First allocate dma memory for IOC */
+       bfa_ioc_mem_claim(&bfa->ioc, bfa_mem_dma_virt(ioc_dma),
+                       bfa_mem_dma_phys(ioc_dma));
 
-       /*
-        * Claim DMA-able memory for the request/response queues and for shadow
-        * ci/pi registers
-        */
+       /* Claim DMA-able memory for the request/response queues */
        per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-                                 BFA_DMA_ALIGN_SZ);
+                               BFA_DMA_ALIGN_SZ);
        per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-                                 BFA_DMA_ALIGN_SZ);
+                               BFA_DMA_ALIGN_SZ);
 
        for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-               iocfc->req_cq_ba[i].kva = dm_kva;
-               iocfc->req_cq_ba[i].pa = dm_pa;
-               memset(dm_kva, 0, per_reqq_sz);
-               dm_kva += per_reqq_sz;
-               dm_pa += per_reqq_sz;
-
-               iocfc->rsp_cq_ba[i].kva = dm_kva;
-               iocfc->rsp_cq_ba[i].pa = dm_pa;
-               memset(dm_kva, 0, per_rspq_sz);
-               dm_kva += per_rspq_sz;
-               dm_pa += per_rspq_sz;
+               reqq_dma = BFA_MEM_REQQ_DMA(bfa, i);
+               iocfc->req_cq_ba[i].kva = bfa_mem_dma_virt(reqq_dma);
+               iocfc->req_cq_ba[i].pa = bfa_mem_dma_phys(reqq_dma);
+               memset(iocfc->req_cq_ba[i].kva, 0, per_reqq_sz);
+
+               rspq_dma = BFA_MEM_RSPQ_DMA(bfa, i);
+               iocfc->rsp_cq_ba[i].kva = bfa_mem_dma_virt(rspq_dma);
+               iocfc->rsp_cq_ba[i].pa = bfa_mem_dma_phys(rspq_dma);
+               memset(iocfc->rsp_cq_ba[i].kva, 0, per_rspq_sz);
        }
 
+       /* Claim IOCFC dma memory - for shadow CI/PI */
+       dm_kva = bfa_mem_dma_virt(iocfc_dma);
+       dm_pa  = bfa_mem_dma_phys(iocfc_dma);
+
        for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
                iocfc->req_cq_shadow_ci[i].kva = dm_kva;
                iocfc->req_cq_shadow_ci[i].pa = dm_pa;
@@ -658,36 +644,27 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
                dm_pa += BFA_CACHELINE_SZ;
        }
 
-       /*
-        * Claim DMA-able memory for the config info page
-        */
+       /* Claim IOCFC dma memory - for the config info page */
        bfa->iocfc.cfg_info.kva = dm_kva;
        bfa->iocfc.cfg_info.pa = dm_pa;
        bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
        dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
        dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
 
-       /*
-        * Claim DMA-able memory for the config response
-        */
+       /* Claim IOCFC dma memory - for the config response */
        bfa->iocfc.cfgrsp_dma.kva = dm_kva;
        bfa->iocfc.cfgrsp_dma.pa = dm_pa;
        bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
-
-       dm_kva +=
-               BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-                           BFA_CACHELINE_SZ);
+       dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+                       BFA_CACHELINE_SZ);
        dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-                            BFA_CACHELINE_SZ);
-
-
-       bfa_meminfo_dma_virt(meminfo) = dm_kva;
-       bfa_meminfo_dma_phys(meminfo) = dm_pa;
+                       BFA_CACHELINE_SZ);
 
+       /* Claim IOCFC kva memory */
        dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
        if (dbgsz > 0) {
-               bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
-               bfa_meminfo_kva(meminfo) += dbgsz;
+               bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
+               bfa_mem_kva_curp(iocfc) += dbgsz;
        }
 }
 
@@ -701,7 +678,7 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
 
        bfa->queue_process = BFA_TRUE;
        for (i = 0; i < BFI_IOC_MAX_CQS; i++)
-               bfa_isr_rspq_ack(bfa, i);
+               bfa_isr_rspq_ack(bfa, i, bfa_rspq_ci(bfa, i));
 
        for (i = 0; hal_mods[i]; i++)
                hal_mods[i]->start(bfa);
@@ -747,6 +724,16 @@ bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
                bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
 }
 
+static void
+bfa_iocfc_enable_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+       struct bfa_s    *bfa = bfa_arg;
+       struct bfad_s *bfad = bfa->bfad;
+
+       if (compl)
+               complete(&bfad->enable_comp);
+}
+
 static void
 bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
 {
@@ -830,8 +817,12 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
 
        if (iocfc->action == BFA_IOCFC_ACT_INIT)
                bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
-       else
+       else {
+               if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
+                       bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
+                                       bfa_iocfc_enable_cb, bfa);
                bfa_iocfc_start_submod(bfa);
+       }
 }
 void
 bfa_iocfc_reset_queues(struct bfa_s *bfa)
@@ -1040,6 +1031,9 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
                if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
                        bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
                                     bfa_iocfc_init_cb, bfa);
+               else if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
+                       bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
+                                       bfa_iocfc_enable_cb, bfa);
                return;
        }
 
@@ -1102,15 +1096,47 @@ bfa_iocfc_reset_cbfn(void *bfa_arg)
  * Query IOC memory requirement information.
  */
 void
-bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-                 u32 *dm_len)
+bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+                 struct bfa_s *bfa)
 {
-       /* dma memory for IOC */
-       *dm_len += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+       int q, per_reqq_sz, per_rspq_sz;
+       struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
+       struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
+       struct bfa_mem_kva_s *iocfc_kva = BFA_MEM_IOCFC_KVA(bfa);
+       u32     dm_len = 0;
+
+       /* dma memory setup for IOC */
+       bfa_mem_dma_setup(meminfo, ioc_dma,
+               BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ));
+
+       /* dma memory setup for REQ/RSP queues */
+       per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+                               BFA_DMA_ALIGN_SZ);
+       per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+                               BFA_DMA_ALIGN_SZ);
+
+       for (q = 0; q < cfg->fwcfg.num_cqs; q++) {
+               bfa_mem_dma_setup(meminfo, BFA_MEM_REQQ_DMA(bfa, q),
+                               per_reqq_sz);
+               bfa_mem_dma_setup(meminfo, BFA_MEM_RSPQ_DMA(bfa, q),
+                               per_rspq_sz);
+       }
+
+       /* IOCFC dma memory - calculate Shadow CI/PI size */
+       for (q = 0; q < cfg->fwcfg.num_cqs; q++)
+               dm_len += (2 * BFA_CACHELINE_SZ);
+
+       /* IOCFC dma memory - calculate config info / rsp size */
+       dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+       dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+                       BFA_CACHELINE_SZ);
+
+       /* dma memory setup for IOCFC */
+       bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len);
 
-       bfa_iocfc_fw_cfg_sz(cfg, dm_len);
-       bfa_iocfc_cqs_sz(cfg, dm_len);
-       *km_len += (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+       /* kva memory setup for IOCFC */
+       bfa_mem_kva_setup(meminfo, iocfc_kva,
+                       ((bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0));
 }
 
 /*
@@ -1118,7 +1144,7 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
  */
 void
 bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-                struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+                struct bfa_pcidev_s *pcidev)
 {
        int             i;
        struct bfa_ioc_s *ioc = &bfa->ioc;
@@ -1135,7 +1161,7 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
 
        bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
-       bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+       bfa_iocfc_mem_claim(bfa, cfg);
        INIT_LIST_HEAD(&bfa->timer_mod.timer_q);
 
        INIT_LIST_HEAD(&bfa->comp_q);
@@ -1259,12 +1285,12 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
 }
 
 void
-bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa)
 {
        struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
 
        iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
-       bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+       bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase[seg_no], snsbase_pa);
 }
 /*
  * Enable IOC after it is disabled.
@@ -1274,6 +1300,7 @@ bfa_iocfc_enable(struct bfa_s *bfa)
 {
        bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
                     "IOC Enable");
+       bfa->iocfc.action = BFA_IOCFC_ACT_ENABLE;
        bfa_ioc_enable(&bfa->ioc);
 }
 
@@ -1353,34 +1380,49 @@ bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
  *                     starting address for each block and provide the same
  *                     structure as input parameter to bfa_attach() call.
  *
+ * @param[in] bfa -    pointer to the bfa structure, used while fetching the
+ *                     dma, kva memory information of the bfa sub-modules.
+ *
  * @return void
  *
  * Special Considerations: @note
  */
 void
-bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
+bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+               struct bfa_s *bfa)
 {
        int             i;
-       u32     km_len = 0, dm_len = 0;
+       struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa);
+       struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
+       struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa);
+       struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa);
+       struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
+       struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
+       struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa);
 
        WARN_ON((cfg == NULL) || (meminfo == NULL));
 
        memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s));
-       meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type =
-               BFA_MEM_TYPE_KVA;
-       meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type =
-               BFA_MEM_TYPE_DMA;
-
-       bfa_iocfc_meminfo(cfg, &km_len, &dm_len);
 
-       for (i = 0; hal_mods[i]; i++)
-               hal_mods[i]->meminfo(cfg, &km_len, &dm_len);
+       /* Initialize the DMA & KVA meminfo queues */
+       INIT_LIST_HEAD(&meminfo->dma_info.qe);
+       INIT_LIST_HEAD(&meminfo->kva_info.qe);
 
-       dm_len += bfa_port_meminfo();
-       dm_len += bfa_ablk_meminfo();
+       bfa_iocfc_meminfo(cfg, meminfo, bfa);
 
-       meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len;
-       meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->meminfo(cfg, meminfo, bfa);
+
+       /* dma info setup */
+       bfa_mem_dma_setup(meminfo, port_dma, bfa_port_meminfo());
+       bfa_mem_dma_setup(meminfo, ablk_dma, bfa_ablk_meminfo());
+       bfa_mem_dma_setup(meminfo, cee_dma, bfa_cee_meminfo());
+       bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo());
+       bfa_mem_dma_setup(meminfo, flash_dma,
+                         bfa_flash_meminfo(cfg->drvcfg.min_cfg));
+       bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo());
+       bfa_mem_dma_setup(meminfo, phy_dma,
+                         bfa_phy_meminfo(cfg->drvcfg.min_cfg));
 }
 
 /*
@@ -1413,29 +1455,46 @@ void
 bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
               struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 {
-       int                     i;
-       struct bfa_mem_elem_s   *melem;
+       int     i;
+       struct bfa_mem_dma_s *dma_info, *dma_elem;
+       struct bfa_mem_kva_s *kva_info, *kva_elem;
+       struct list_head *dm_qe, *km_qe;
 
        bfa->fcs = BFA_FALSE;
 
        WARN_ON((cfg == NULL) || (meminfo == NULL));
 
-       /*
-        * initialize all memory pointers for iterative allocation
-        */
-       for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
-               melem = meminfo->meminfo + i;
-               melem->kva_curp = melem->kva;
-               melem->dma_curp = melem->dma;
+       /* Initialize memory pointers for iterative allocation */
+       dma_info = &meminfo->dma_info;
+       dma_info->kva_curp = dma_info->kva;
+       dma_info->dma_curp = dma_info->dma;
+
+       kva_info = &meminfo->kva_info;
+       kva_info->kva_curp = kva_info->kva;
+
+       list_for_each(dm_qe, &dma_info->qe) {
+               dma_elem = (struct bfa_mem_dma_s *) dm_qe;
+               dma_elem->kva_curp = dma_elem->kva;
+               dma_elem->dma_curp = dma_elem->dma;
        }
 
-       bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev);
+       list_for_each(km_qe, &kva_info->qe) {
+               kva_elem = (struct bfa_mem_kva_s *) km_qe;
+               kva_elem->kva_curp = kva_elem->kva;
+       }
 
-       for (i = 0; hal_mods[i]; i++)
-               hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
+       bfa_iocfc_attach(bfa, bfad, cfg, pcidev);
 
-       bfa_com_port_attach(bfa, meminfo);
-       bfa_com_ablk_attach(bfa, meminfo);
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->attach(bfa, bfad, cfg, pcidev);
+
+       bfa_com_port_attach(bfa);
+       bfa_com_ablk_attach(bfa);
+       bfa_com_cee_attach(bfa);
+       bfa_com_sfp_attach(bfa);
+       bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
+       bfa_com_diag_attach(bfa);
+       bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg);
 }
 
 /*