Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
Linus Torvalds [Sat, 23 Jul 2011 18:13:11 +0000 (11:13 -0700)]
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (77 commits)
  [SCSI] fix crash in scsi_dispatch_cmd()
  [SCSI] sr: check_events() ignore GET_EVENT when TUR says otherwise
  [SCSI] bnx2i: Fixed kernel panic due to illegal usage of sc->request->cpu
  [SCSI] bfa: Update the driver version to 3.0.2.1
  [SCSI] bfa: Driver and BSG enhancements.
  [SCSI] bfa: Added support to query PHY.
  [SCSI] bfa: Added HBA diagnostics support.
  [SCSI] bfa: Added support for flash configuration
  [SCSI] bfa: Added support to obtain SFP info.
  [SCSI] bfa: Added support for CEE info and stats query.
  [SCSI] bfa: Extend BSG interface.
  [SCSI] bfa: FCS bug fixes.
  [SCSI] bfa: DMA memory allocation enhancement.
  [SCSI] bfa: Brocade-1860 Fabric Adapter vHBA support.
  [SCSI] bfa: Brocade-1860 Fabric Adapter PLL init fixes.
  [SCSI] bfa: Added Fabric Assigned Address(FAA) support
  [SCSI] bfa: IOC bug fixes.
  [SCSI] bfa: Enable ASIC block configuration and query.
  [SCSI] bnx2i: Updated copyright and bump version
  [SCSI] bnx2i: Modified to skip CNIC registration if iSCSI is not supported
  ...

Fix up some trivial conflicts in:
 - drivers/scsi/bnx2fc/{bnx2fc.h,bnx2fc_fcoe.c}:
Crazy broadcom version number conflicts
 - drivers/target/tcm_fc/tfc_cmd.c
Just trivial cleanups done on adjacent lines

96 files changed:
MAINTAINERS
block/blk-core.c
block/blk-exec.c
drivers/firmware/iscsi_ibft.c
drivers/scsi/aha152x.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/atari_scsi.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/bfa/Makefile
drivers/scsi/bfa/bfa.h
drivers/scsi/bfa/bfa_core.c
drivers/scsi/bfa/bfa_defs.h
drivers/scsi/bfa/bfa_defs_fcs.h
drivers/scsi/bfa/bfa_defs_svc.h
drivers/scsi/bfa/bfa_fc.h
drivers/scsi/bfa/bfa_fcbuild.c
drivers/scsi/bfa/bfa_fcbuild.h
drivers/scsi/bfa/bfa_fcpim.c
drivers/scsi/bfa/bfa_fcpim.h
drivers/scsi/bfa/bfa_fcs.c
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_fcpim.c
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfa_fcs_rport.c
drivers/scsi/bfa/bfa_hw_cb.c
drivers/scsi/bfa/bfa_hw_ct.c
drivers/scsi/bfa/bfa_ioc.c
drivers/scsi/bfa/bfa_ioc.h
drivers/scsi/bfa/bfa_ioc_cb.c
drivers/scsi/bfa/bfa_ioc_ct.c
drivers/scsi/bfa/bfa_modules.h
drivers/scsi/bfa/bfa_port.c
drivers/scsi/bfa/bfa_port.h
drivers/scsi/bfa/bfa_svc.c
drivers/scsi/bfa/bfa_svc.h
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_attr.c
drivers/scsi/bfa/bfad_bsg.c [new file with mode: 0644]
drivers/scsi/bfa/bfad_bsg.h [new file with mode: 0644]
drivers/scsi/bfa/bfad_debugfs.c
drivers/scsi/bfa/bfad_drv.h
drivers/scsi/bfa/bfad_im.c
drivers/scsi/bfa/bfad_im.h
drivers/scsi/bfa/bfi.h
drivers/scsi/bfa/bfi_cbreg.h [deleted file]
drivers/scsi/bfa/bfi_ctreg.h [deleted file]
drivers/scsi/bfa/bfi_ms.h
drivers/scsi/bfa/bfi_reg.h [new file with mode: 0644]
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2i/57xx_iscsi_constants.h
drivers/scsi/bnx2i/57xx_iscsi_hsi.h
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_init.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/bnx2i/bnx2i_sysfs.c
drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/iscsi_boot_sysfs.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/libfc/fc_exch.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/libiscsi.c
drivers/scsi/libiscsi_tcp.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/mac_scsi.c
drivers/scsi/mpt2sas/mpi/mpi2.h
drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
drivers/scsi/mpt2sas/mpi/mpi2_init.h
drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/mpt2sas/mpt2sas_debug.h
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt2sas/mpt2sas_transport.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_lib.c
drivers/scsi/ses.c
drivers/scsi/sr.c
drivers/scsi/sr.h
drivers/scsi/sun3_NCR5380.c
drivers/scsi/sun3_scsi.c
drivers/scsi/sun3_scsi_vme.c
drivers/target/tcm_fc/tfc_cmd.c
include/linux/iscsi_boot_sysfs.h
include/scsi/iscsi_proto.h
include/scsi/libfc.h
include/scsi/libiscsi.h

index 7521440..612316c 100644 (file)
@@ -1553,6 +1553,12 @@ L:       linux-wireless@vger.kernel.org
 S:     Supported
 F:     drivers/staging/brcm80211/
 
+BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
+M:     Bhanu Prakash Gollapudi <bprakash@broadcom.com>
+L:     linux-scsi@vger.kernel.org
+S:     Supported
+F:     drivers/scsi/bnx2fc/
+
 BROCADE BFA FC SCSI DRIVER
 M:     Jing Huang <huangj@brocade.com>
 L:     linux-scsi@vger.kernel.org
@@ -1775,7 +1781,8 @@ F:        include/linux/clk.h
 
 CISCO FCOE HBA DRIVER
 M:     Abhijeet Joglekar <abjoglek@cisco.com>
-M:     Joe Eykholt <jeykholt@cisco.com>
+M:     Venkata Siva Vijayendra Bhamidipati <vbhamidi@cisco.com>
+M:     Brian Uchino <buchino@cisco.com>
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     drivers/scsi/fnic/
index d2f8f40..1d49e1c 100644 (file)
@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
 {
        struct request *rq;
 
+       if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+               return NULL;
+
        BUG_ON(rw != READ && rw != WRITE);
 
        spin_lock_irq(q->queue_lock);
index 8a0e7ec..a1ebceb 100644 (file)
@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
 {
        int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
 
+       if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
+               rq->errors = -ENXIO;
+               if (rq->end_io)
+                       rq->end_io(rq, rq->errors);
+               return;
+       }
+
        rq->rq_disk = bd_disk;
        rq->end_io = done;
        WARN_ON(irqs_disabled());
index ce33f46..c811cb1 100644 (file)
@@ -566,6 +566,11 @@ static mode_t __init ibft_check_initiator_for(void *data, int type)
        return rc;
 }
 
+static void ibft_kobj_release(void *data)
+{
+       kfree(data);
+}
+
 /*
  * Helper function for ibft_register_kobjects.
  */
@@ -595,7 +600,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
                boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
                                                ibft_kobj,
                                                ibft_attr_show_initiator,
-                                               ibft_check_initiator_for);
+                                               ibft_check_initiator_for,
+                                               ibft_kobj_release);
                if (!boot_kobj) {
                        rc = -ENOMEM;
                        goto free_ibft_obj;
@@ -610,7 +616,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
                boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
                                                       ibft_kobj,
                                                       ibft_attr_show_nic,
-                                                      ibft_check_nic_for);
+                                                      ibft_check_nic_for,
+                                                      ibft_kobj_release);
                if (!boot_kobj) {
                        rc = -ENOMEM;
                        goto free_ibft_obj;
@@ -625,7 +632,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
                boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
                                                     ibft_kobj,
                                                     ibft_attr_show_target,
-                                                    ibft_check_tgt_for);
+                                                    ibft_check_tgt_for,
+                                                    ibft_kobj_release);
                if (!boot_kobj) {
                        rc = -ENOMEM;
                        goto free_ibft_obj;
index c5169f0..f17c92c 100644 (file)
@@ -422,10 +422,19 @@ MODULE_PARM_DESC(aha152x1, "parameters for second controller");
 
 #ifdef __ISAPNP__
 static struct isapnp_device_id id_table[] __devinitdata = {
-       { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-               ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), 0 },
-       { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-               ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1530), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1515), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1520), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2015), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1522), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2215), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1530), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3015), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1532), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3215), 0 },
+       { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x6360), 0 },
        { ISAPNP_DEVICE_SINGLE_END, }
 };
 MODULE_DEVICE_TABLE(isapnp, id_table);
index ea439f9..2db79b4 100644 (file)
@@ -892,6 +892,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        return 0;
 }
 
+static void NCR5380_exit(struct Scsi_Host *instance)
+{
+       /* Empty, as we didn't schedule any delayed work */
+}
+
 /*
  * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
  *     void (*done)(Scsi_Cmnd *))
@@ -914,7 +919,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
 {
        SETUP_HOSTDATA(cmd->device->host);
        Scsi_Cmnd *tmp;
-       int oldto;
        unsigned long flags;
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
index 3e8658e..04a154f 100644 (file)
@@ -730,6 +730,7 @@ int atari_scsi_release(struct Scsi_Host *sh)
                free_irq(IRQ_TT_MFP_SCSI, sh);
        if (atari_dma_buffer)
                atari_stram_free(atari_dma_buffer);
+       NCR5380_exit(sh);
        return 1;
 }
 
index 94b9a07..0a9bdfa 100644 (file)
@@ -215,73 +215,62 @@ unlock:
 static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
 {
        struct beiscsi_hba *phba = data;
+       struct mgmt_session_info *boot_sess = &phba->boot_sess;
+       struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];
        char *str = buf;
        int rc;
 
        switch (type) {
        case ISCSI_BOOT_TGT_NAME:
                rc = sprintf(buf, "%.*s\n",
-                               (int)strlen(phba->boot_sess.target_name),
-                               (char *)&phba->boot_sess.target_name);
+                           (int)strlen(boot_sess->target_name),
+                           (char *)&boot_sess->target_name);
                break;
        case ISCSI_BOOT_TGT_IP_ADDR:
-               if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1)
+               if (boot_conn->dest_ipaddr.ip_type == 0x1)
                        rc = sprintf(buf, "%pI4\n",
-                               (char *)&phba->boot_sess.conn_list[0].
-                               dest_ipaddr.ip_address);
+                               (char *)&boot_conn->dest_ipaddr.ip_address);
                else
                        rc = sprintf(str, "%pI6\n",
-                               (char *)&phba->boot_sess.conn_list[0].
-                               dest_ipaddr.ip_address);
+                               (char *)&boot_conn->dest_ipaddr.ip_address);
                break;
        case ISCSI_BOOT_TGT_PORT:
-               rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0].
-                                 dest_port);
+               rc = sprintf(str, "%d\n", boot_conn->dest_port);
                break;
 
        case ISCSI_BOOT_TGT_CHAP_NAME:
                rc = sprintf(str,  "%.*s\n",
-                                     phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     target_chap_name_length,
-                                     (char *)&phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     target_chap_name);
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            target_chap_name_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.target_chap_name);
                break;
        case ISCSI_BOOT_TGT_CHAP_SECRET:
                rc = sprintf(str,  "%.*s\n",
-                                     phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     target_secret_length,
-                                     (char *)&phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     target_secret);
-
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            target_secret_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.target_secret);
                break;
        case ISCSI_BOOT_TGT_REV_CHAP_NAME:
                rc = sprintf(str,  "%.*s\n",
-                                     phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     intr_chap_name_length,
-                                     (char *)&phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     intr_chap_name);
-
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            intr_chap_name_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.intr_chap_name);
                break;
        case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
-                       rc = sprintf(str,  "%.*s\n",
-                                     phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     intr_secret_length,
-                                     (char *)&phba->boot_sess.conn_list[0].
-                                     negotiated_login_options.auth_data.chap.
-                                     intr_secret);
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            intr_secret_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.intr_secret);
                break;
        case ISCSI_BOOT_TGT_FLAGS:
-                       rc = sprintf(str, "2\n");
+               rc = sprintf(str, "2\n");
                break;
        case ISCSI_BOOT_TGT_NIC_ASSOC:
-                       rc = sprintf(str, "0\n");
+               rc = sprintf(str, "0\n");
                break;
        default:
                rc = -ENOSYS;
@@ -315,10 +304,10 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
 
        switch (type) {
        case ISCSI_BOOT_ETH_FLAGS:
-                       rc = sprintf(str, "2\n");
+               rc = sprintf(str, "2\n");
                break;
        case ISCSI_BOOT_ETH_INDEX:
-                       rc = sprintf(str, "0\n");
+               rc = sprintf(str, "0\n");
                break;
        case ISCSI_BOOT_ETH_MAC:
                rc  = beiscsi_get_macaddr(buf, phba);
@@ -391,40 +380,6 @@ static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
        return rc;
 }
 
-static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
-{
-       struct iscsi_boot_kobj *boot_kobj;
-
-       phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
-       if (!phba->boot_kset)
-               return -ENOMEM;
-
-       /* get boot info using mgmt cmd */
-       boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
-                                            beiscsi_show_boot_tgt_info,
-                                            beiscsi_tgt_get_attr_visibility);
-       if (!boot_kobj)
-               goto free_kset;
-
-       boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
-                                            beiscsi_show_boot_ini_info,
-                                            beiscsi_ini_get_attr_visibility);
-       if (!boot_kobj)
-               goto free_kset;
-
-       boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
-                                            beiscsi_show_boot_eth_info,
-                                            beiscsi_eth_get_attr_visibility);
-       if (!boot_kobj)
-               goto free_kset;
-       return 0;
-
-free_kset:
-       if (phba->boot_kset)
-               iscsi_boot_destroy_kset(phba->boot_kset);
-       return -ENOMEM;
-}
-
 /*------------------- PCI Driver operations and data ----------------- */
 static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
        { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
@@ -483,14 +438,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
        if (iscsi_host_add(shost, &phba->pcidev->dev))
                goto free_devices;
 
-       if (beiscsi_setup_boot_info(phba))
-               /*
-                * log error but continue, because we may not be using
-                * iscsi boot.
-                */
-               shost_printk(KERN_ERR, phba->shost, "Could not set up "
-               "iSCSI boot info.");
-
        return phba;
 
 free_devices:
@@ -3511,6 +3458,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
        unsigned int tag, wrb_num;
        unsigned short status, extd_status;
        struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+       int ret = -ENOMEM;
 
        tag = beiscsi_get_boot_target(phba);
        if (!tag) {
@@ -3535,8 +3483,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
        boot_resp = embedded_payload(wrb);
 
        if (boot_resp->boot_session_handle < 0) {
-               printk(KERN_ERR "No Boot Session for this pci_func,"
-                       "session Hndl = %d\n", boot_resp->boot_session_handle);
+               shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n");
                return -ENXIO;
        }
 
@@ -3574,14 +3521,70 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
        wrb = queue_get_wrb(mccq, wrb_num);
        free_mcc_tag(&phba->ctrl, tag);
        session_resp = nonemb_cmd.va ;
+
        memcpy(&phba->boot_sess, &session_resp->session_info,
               sizeof(struct mgmt_session_info));
-       pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
-                   nonemb_cmd.va, nonemb_cmd.dma);
-       return 0;
+       ret = 0;
+
 boot_freemem:
        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                    nonemb_cmd.va, nonemb_cmd.dma);
+       return ret;
+}
+
+static void beiscsi_boot_release(void *data)
+{
+       struct beiscsi_hba *phba = data;
+
+       scsi_host_put(phba->shost);
+}
+
+static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+{
+       struct iscsi_boot_kobj *boot_kobj;
+
+       /* get boot info using mgmt cmd */
+       if (beiscsi_get_boot_info(phba))
+               /* Try to see if we can carry on without this */
+               return 0;
+
+       phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
+       if (!phba->boot_kset)
+               return -ENOMEM;
+
+       /* get a ref because the show function will ref the phba */
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
+                                            beiscsi_show_boot_tgt_info,
+                                            beiscsi_tgt_get_attr_visibility,
+                                            beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
+                                               beiscsi_show_boot_ini_info,
+                                               beiscsi_ini_get_attr_visibility,
+                                               beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
+                                              beiscsi_show_boot_eth_info,
+                                              beiscsi_eth_get_attr_visibility,
+                                              beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+       return 0;
+
+put_shost:
+       scsi_host_put(phba->shost);
+free_kset:
+       iscsi_boot_destroy_kset(phba->boot_kset);
        return -ENOMEM;
 }
 
@@ -3963,11 +3966,10 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
        }
        memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
               dw[offsetof(struct amap_pdu_data_out, lun) / 32],
-              io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
+              &io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
 
        AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
-                     cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
-                                 lun[0]));
+                     cpu_to_be16(*(unsigned short *)&io_task->cmd_bhs->iscsi_hdr.lun));
        AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
        AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
                      io_task->pwrb_handle->wrb_index);
@@ -4150,8 +4152,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,
                            phba->ctrl.mbox_mem_alloced.dma);
-       if (phba->boot_kset)
-               iscsi_boot_destroy_kset(phba->boot_kset);
+       iscsi_boot_destroy_kset(phba->boot_kset);
        iscsi_host_remove(phba->shost);
        pci_dev_put(phba->pcidev);
        iscsi_host_free(phba->shost);
@@ -4310,11 +4311,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto free_blkenbld;
        }
        hwi_enable_intr(phba);
-       ret = beiscsi_get_boot_info(phba);
-       if (ret < 0) {
-               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
-                            "No Boot Devices !!!!!\n");
-       }
+
+       if (beiscsi_setup_boot_info(phba))
+               /*
+                * log error but continue, because we may not be using
+                * iscsi boot.
+                */
+               shost_printk(KERN_ERR, phba->shost, "Could not set up "
+                            "iSCSI boot info.");
+
        SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
        return 0;
 
index 4ce6f49..475cf92 100644 (file)
@@ -1,6 +1,6 @@
 obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
 
-bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
+bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o bfad_bsg.o
 bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
 bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
 bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o
index 7be6b5a..3b0af11 100644 (file)
@@ -27,7 +27,6 @@
 struct bfa_s;
 
 typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
-typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
 
 /*
  * Interrupt message handlers
@@ -54,7 +53,8 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
         ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
                   + bfa_reqq_pi((__bfa), (__reqq)))))
 
-#define bfa_reqq_produce(__bfa, __reqq)        do {                            \
+#define bfa_reqq_produce(__bfa, __reqq, __mh)  do {                    \
+               (__mh).mtag.h2i.qid     = (__bfa)->iocfc.hw_qid[__reqq];\
                (__bfa)->iocfc.req_cq_pi[__reqq]++;                     \
                (__bfa)->iocfc.req_cq_pi[__reqq] &=                     \
                        ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \
@@ -76,16 +76,6 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
 } while (0)
 
 /*
- * Queue element to wait for room in request queue. FIFO order is
- * maintained when fullfilling requests.
- */
-struct bfa_reqq_wait_s {
-       struct list_head        qe;
-       void            (*qresume) (void *cbarg);
-       void            *cbarg;
-};
-
-/*
  * Circular queue usage assignments
  */
 enum {
@@ -128,18 +118,6 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
 
 #define bfa_reqq_wcancel(__wqe)        list_del(&(__wqe)->qe)
 
-
-/*
- * Generic BFA callback element.
- */
-struct bfa_cb_qe_s {
-       struct list_head         qe;
-       bfa_cb_cbfn_t  cbfn;
-       bfa_boolean_t   once;
-       u32             rsvd;
-       void           *cbarg;
-};
-
 #define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {    \
                (__hcb_qe)->cbfn  = (__cbfn);      \
                (__hcb_qe)->cbarg = (__cbarg);      \
@@ -172,44 +150,14 @@ struct bfa_pciid_s {
 
 extern char     bfa_version[];
 
-/*
- * BFA memory resources
- */
-enum bfa_mem_type {
-       BFA_MEM_TYPE_KVA = 1,   /*  Kernel Virtual Memory *(non-dma-able) */
-       BFA_MEM_TYPE_DMA = 2,   /*  DMA-able memory */
-       BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
-};
-
-struct bfa_mem_elem_s {
-       enum bfa_mem_type mem_type;     /* see enum bfa_mem_type */
-       u32     mem_len;        /*  Total Length in Bytes       */
-       u8              *kva;           /*  kernel virtual address      */
-       u64     dma;            /*  dma address if DMA memory   */
-       u8              *kva_curp;      /*  kva allocation cursor       */
-       u64     dma_curp;       /*  dma allocation cursor       */
-};
-
-struct bfa_meminfo_s {
-       struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
-};
-#define bfa_meminfo_kva(_m)                            \
-       ((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
-#define bfa_meminfo_dma_virt(_m)                       \
-       ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
-#define bfa_meminfo_dma_phys(_m)                       \
-       ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
-
 struct bfa_iocfc_regs_s {
        void __iomem    *intr_status;
        void __iomem    *intr_mask;
        void __iomem    *cpe_q_pi[BFI_IOC_MAX_CQS];
        void __iomem    *cpe_q_ci[BFI_IOC_MAX_CQS];
-       void __iomem    *cpe_q_depth[BFI_IOC_MAX_CQS];
        void __iomem    *cpe_q_ctrl[BFI_IOC_MAX_CQS];
        void __iomem    *rme_q_ci[BFI_IOC_MAX_CQS];
        void __iomem    *rme_q_pi[BFI_IOC_MAX_CQS];
-       void __iomem    *rme_q_depth[BFI_IOC_MAX_CQS];
        void __iomem    *rme_q_ctrl[BFI_IOC_MAX_CQS];
 };
 
@@ -231,25 +179,55 @@ struct bfa_hwif_s {
        void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
        void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
        void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
-       void (*hw_msix_install)(struct bfa_s *bfa);
+       void (*hw_msix_ctrl_install)(struct bfa_s *bfa);
+       void (*hw_msix_queue_install)(struct bfa_s *bfa);
        void (*hw_msix_uninstall)(struct bfa_s *bfa);
        void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
        void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
                                u32 *nvecs, u32 *maxvec);
        void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
                                       u32 *end);
+       int     cpe_vec_q0;
+       int     rme_vec_q0;
 };
 typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
 
+struct bfa_faa_cbfn_s {
+       bfa_cb_iocfc_t  faa_cbfn;
+       void            *faa_cbarg;
+};
+
+#define BFA_FAA_ENABLED                1
+#define BFA_FAA_DISABLED       2
+
+/*
+ *     FAA attributes
+ */
+struct bfa_faa_attr_s {
+       wwn_t   faa;
+       u8      faa_state;
+       u8      pwwn_source;
+       u8      rsvd[6];
+};
+
+struct bfa_faa_args_s {
+       struct bfa_faa_attr_s   *faa_attr;
+       struct bfa_faa_cbfn_s   faa_cb;
+       u8                      faa_state;
+       bfa_boolean_t           busy;
+};
+
 struct bfa_iocfc_s {
        struct bfa_s            *bfa;
        struct bfa_iocfc_cfg_s  cfg;
        int                     action;
        u32             req_cq_pi[BFI_IOC_MAX_CQS];
        u32             rsp_cq_ci[BFI_IOC_MAX_CQS];
+       u8              hw_qid[BFI_IOC_MAX_CQS];
        struct bfa_cb_qe_s      init_hcb_qe;
        struct bfa_cb_qe_s      stop_hcb_qe;
        struct bfa_cb_qe_s      dis_hcb_qe;
+       struct bfa_cb_qe_s      en_hcb_qe;
        struct bfa_cb_qe_s      stats_hcb_qe;
        bfa_boolean_t           cfgdone;
 
@@ -257,7 +235,6 @@ struct bfa_iocfc_s {
        struct bfi_iocfc_cfg_s *cfginfo;
        struct bfa_dma_s        cfgrsp_dma;
        struct bfi_iocfc_cfgrsp_s *cfgrsp;
-       struct bfi_iocfc_cfg_reply_s *cfg_reply;
        struct bfa_dma_s        req_cq_ba[BFI_IOC_MAX_CQS];
        struct bfa_dma_s        req_cq_shadow_ci[BFI_IOC_MAX_CQS];
        struct bfa_dma_s        rsp_cq_ba[BFI_IOC_MAX_CQS];
@@ -267,18 +244,42 @@ struct bfa_iocfc_s {
        bfa_cb_iocfc_t          updateq_cbfn; /*  bios callback function */
        void                    *updateq_cbarg; /*  bios callback arg */
        u32     intr_mask;
+       struct bfa_faa_args_s   faa_args;
+       struct bfa_mem_dma_s    ioc_dma;
+       struct bfa_mem_dma_s    iocfc_dma;
+       struct bfa_mem_dma_s    reqq_dma[BFI_IOC_MAX_CQS];
+       struct bfa_mem_dma_s    rspq_dma[BFI_IOC_MAX_CQS];
+       struct bfa_mem_kva_s    kva_seg;
 };
 
-#define bfa_lpuid(__bfa)                                               \
-       bfa_ioc_portid(&(__bfa)->ioc)
+#define BFA_MEM_IOC_DMA(_bfa)          (&((_bfa)->iocfc.ioc_dma))
+#define BFA_MEM_IOCFC_DMA(_bfa)                (&((_bfa)->iocfc.iocfc_dma))
+#define BFA_MEM_REQQ_DMA(_bfa, _qno)   (&((_bfa)->iocfc.reqq_dma[(_qno)]))
+#define BFA_MEM_RSPQ_DMA(_bfa, _qno)   (&((_bfa)->iocfc.rspq_dma[(_qno)]))
+#define BFA_MEM_IOCFC_KVA(_bfa)                (&((_bfa)->iocfc.kva_seg))
+
+#define bfa_fn_lpu(__bfa)      \
+       bfi_fn_lpu(bfa_ioc_pcifn(&(__bfa)->ioc), bfa_ioc_portid(&(__bfa)->ioc))
 #define bfa_msix_init(__bfa, __nvecs)                                  \
        ((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
-#define bfa_msix_install(__bfa)                                                \
-       ((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
+#define bfa_msix_ctrl_install(__bfa)                                   \
+       ((__bfa)->iocfc.hwif.hw_msix_ctrl_install(__bfa))
+#define bfa_msix_queue_install(__bfa)                                  \
+       ((__bfa)->iocfc.hwif.hw_msix_queue_install(__bfa))
 #define bfa_msix_uninstall(__bfa)                                      \
        ((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
-#define bfa_isr_mode_set(__bfa, __msix)                                        \
-       ((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
+#define bfa_isr_rspq_ack(__bfa, __queue) do {                          \
+       if ((__bfa)->iocfc.hwif.hw_rspq_ack)                            \
+               (__bfa)->iocfc.hwif.hw_rspq_ack(__bfa, __queue);        \
+} while (0)
+#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))
@@ -290,17 +291,17 @@ struct bfa_iocfc_s {
 /*
  * FC specific IOC functions.
  */
-void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-                      u32 *dm_len);
+void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg,
+                       struct bfa_meminfo_s *meminfo,
+                       struct bfa_s *bfa);
 void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
                      struct bfa_iocfc_cfg_s *cfg,
-                     struct bfa_meminfo_s *meminfo,
                      struct bfa_pcidev_s *pcidev);
 void bfa_iocfc_init(struct bfa_s *bfa);
 void bfa_iocfc_start(struct bfa_s *bfa);
 void bfa_iocfc_stop(struct bfa_s *bfa);
 void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
-void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
+void bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa);
 bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
 void bfa_iocfc_reset_queues(struct bfa_s *bfa);
 
@@ -310,10 +311,10 @@ void bfa_msix_rspq(struct bfa_s *bfa, int vec);
 void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
 
 void bfa_hwcb_reginit(struct bfa_s *bfa);
-void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwcb_msix_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_queue_install(struct bfa_s *bfa);
 void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
 void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
 void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
@@ -321,10 +322,12 @@ void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
 void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
                                 u32 *end);
 void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct2_reginit(struct bfa_s *bfa);
 void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwct_msix_install(struct bfa_s *bfa);
+void bfa_hwct_msix_ctrl_install(struct bfa_s *bfa);
+void bfa_hwct_msix_queue_install(struct bfa_s *bfa);
 void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
 void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
 void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
@@ -377,7 +380,8 @@ void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
 void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
 void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
 void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
-                        struct bfa_meminfo_s *meminfo);
+                       struct bfa_meminfo_s *meminfo,
+                       struct bfa_s *bfa);
 void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
                struct bfa_meminfo_s *meminfo,
                struct bfa_pcidev_s *pcidev);
index 91838c5..c38e589 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "bfad_drv.h"
 #include "bfa_modules.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 
 BFA_TRC_FILE(HAL, CORE);
 
@@ -25,13 +25,14 @@ BFA_TRC_FILE(HAL, CORE);
  * BFA module list terminated by NULL
  */
 static struct bfa_module_s *hal_mods[] = {
+       &hal_mod_fcdiag,
        &hal_mod_sgpg,
        &hal_mod_fcport,
        &hal_mod_fcxp,
        &hal_mod_lps,
        &hal_mod_uf,
        &hal_mod_rport,
-       &hal_mod_fcpim,
+       &hal_mod_fcp,
        NULL
 };
 
@@ -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 */
@@ -51,7 +52,7 @@ static bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
        bfa_fcxp_isr,           /* BFI_MC_FCXP */
        bfa_lps_isr,            /* BFI_MC_LPS */
        bfa_rport_isr,          /* BFI_MC_RPORT */
-       bfa_itnim_isr,          /* BFI_MC_ITNIM */
+       bfa_itn_isr,            /* BFI_MC_ITN */
        bfa_isr_unhandled,      /* BFI_MC_IOIM_READ */
        bfa_isr_unhandled,      /* BFI_MC_IOIM_WRITE */
        bfa_isr_unhandled,      /* BFI_MC_IOIM_IO */
@@ -89,23 +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_port_mem_claim(port, port_dma->kva_curp, port_dma->dma_curp);
+}
+
+/*
+ * ablk module attach
+ */
+static void
+bfa_com_ablk_attach(struct bfa_s *bfa)
+{
+       struct bfa_ablk_s       *ablk = &bfa->modules.ablk;
+       struct bfa_mem_dma_s    *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
+
+       bfa_ablk_attach(ablk, &bfa->ioc);
+       bfa_ablk_memclaim(ablk, ablk_dma->kva_curp, ablk_dma->dma_curp);
+}
+
+static void
+bfa_com_cee_attach(struct bfa_s *bfa)
+{
+       struct bfa_cee_s        *cee = &bfa->modules.cee;
+       struct bfa_mem_dma_s    *cee_dma = BFA_MEM_CEE_DMA(bfa);
+
+       cee->trcmod = bfa->trcmod;
+       bfa_cee_attach(cee, &bfa->ioc, bfa);
+       bfa_cee_mem_claim(cee, cee_dma->kva_curp, cee_dma->dma_curp);
+}
+
+static void
+bfa_com_sfp_attach(struct bfa_s *bfa)
+{
+       struct bfa_sfp_s        *sfp = BFA_SFP_MOD(bfa);
+       struct bfa_mem_dma_s    *sfp_dma = BFA_MEM_SFP_DMA(bfa);
+
+       bfa_sfp_attach(sfp, &bfa->ioc, bfa, bfa->trcmod);
+       bfa_sfp_memclaim(sfp, sfp_dma->kva_curp, sfp_dma->dma_curp);
+}
+
+static void
+bfa_com_flash_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+       struct bfa_flash_s      *flash = BFA_FLASH(bfa);
+       struct bfa_mem_dma_s    *flash_dma = BFA_MEM_FLASH_DMA(bfa);
+
+       bfa_flash_attach(flash, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+       bfa_flash_memclaim(flash, flash_dma->kva_curp,
+                          flash_dma->dma_curp, mincfg);
+}
+
+static void
+bfa_com_diag_attach(struct bfa_s *bfa)
+{
+       struct bfa_diag_s       *diag = BFA_DIAG_MOD(bfa);
+       struct bfa_mem_dma_s    *diag_dma = BFA_MEM_DIAG_DMA(bfa);
+
+       bfa_diag_attach(diag, &bfa->ioc, bfa, bfa_fcport_beacon, bfa->trcmod);
+       bfa_diag_memclaim(diag, diag_dma->kva_curp, diag_dma->dma_curp);
+}
+
+static void
+bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+       struct bfa_phy_s        *phy = BFA_PHY(bfa);
+       struct bfa_mem_dma_s    *phy_dma = BFA_MEM_PHY_DMA(bfa);
 
-       bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
-       bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+       bfa_phy_attach(phy, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+       bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg);
 }
 
 /*
@@ -122,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
@@ -173,10 +230,92 @@ bfa_reqq_resume(struct bfa_s *bfa, int qid)
        }
 }
 
+static inline void
+bfa_isr_rspq(struct bfa_s *bfa, int qid)
+{
+       struct bfi_msg_s *m;
+       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);
+
+       while (ci != pi) {
+               m = bfa_rspq_elem(bfa, qid, ci);
+               WARN_ON(m->mhdr.msg_class >= BFI_MC_MAX);
+
+               bfa_isrs[m->mhdr.msg_class] (bfa, m);
+               CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
+       }
+
+       /*
+        * update CI
+        */
+       bfa_rspq_ci(bfa, qid) = pi;
+       writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
+       mmiowb();
+
+       /*
+        * Resume any pending requests in the corresponding reqq.
+        */
+       waitq = bfa_reqq(bfa, qid);
+       if (!list_empty(waitq))
+               bfa_reqq_resume(bfa, qid);
+}
+
+static inline void
+bfa_isr_reqq(struct bfa_s *bfa, int qid)
+{
+       struct list_head *waitq;
+
+       bfa_isr_reqq_ack(bfa, qid);
+
+       /*
+        * Resume any pending requests in the corresponding reqq.
+        */
+       waitq = bfa_reqq(bfa, qid);
+       if (!list_empty(waitq))
+               bfa_reqq_resume(bfa, qid);
+}
+
 void
 bfa_msix_all(struct bfa_s *bfa, int vec)
 {
-       bfa_intx(bfa);
+       u32     intr, qintr;
+       int     queue;
+
+       intr = readl(bfa->iocfc.bfa_regs.intr_status);
+       if (!intr)
+               return;
+
+       /*
+        * RME completion queue interrupt
+        */
+       qintr = intr & __HFN_INT_RME_MASK;
+       if (qintr && bfa->queue_process) {
+               for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+                       bfa_isr_rspq(bfa, queue);
+       }
+
+       intr &= ~qintr;
+       if (!intr)
+               return;
+
+       /*
+        * CPE completion queue interrupt
+        */
+       qintr = intr & __HFN_INT_CPE_MASK;
+       if (qintr && bfa->queue_process) {
+               for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+                       bfa_isr_reqq(bfa, queue);
+       }
+       intr &= ~qintr;
+       if (!intr)
+               return;
+
+       bfa_msix_lpu_err(bfa, intr);
 }
 
 bfa_boolean_t
@@ -189,16 +328,19 @@ bfa_intx(struct bfa_s *bfa)
        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
         */
        qintr = intr & __HFN_INT_RME_MASK;
-       writel(qintr, bfa->iocfc.bfa_regs.intr_status);
-
-       for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-               if (intr & (__HFN_INT_RME_Q0 << queue))
-                       bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+       if (qintr && bfa->queue_process) {
+               for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+                       bfa_isr_rspq(bfa, queue);
        }
+
        intr &= ~qintr;
        if (!intr)
                return BFA_TRUE;
@@ -207,11 +349,9 @@ bfa_intx(struct bfa_s *bfa)
         * CPE completion queue interrupt
         */
        qintr = intr & __HFN_INT_CPE_MASK;
-       writel(qintr, bfa->iocfc.bfa_regs.intr_status);
-
-       for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-               if (intr & (__HFN_INT_CPE_Q0 << queue))
-                       bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+       if (qintr && bfa->queue_process) {
+               for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+                       bfa_isr_reqq(bfa, queue);
        }
        intr &= ~qintr;
        if (!intr)
@@ -225,32 +365,25 @@ bfa_intx(struct bfa_s *bfa)
 void
 bfa_isr_enable(struct bfa_s *bfa)
 {
-       u32 intr_unmask;
+       u32 umsk;
        int pci_func = bfa_ioc_pcifn(&bfa->ioc);
 
        bfa_trc(bfa, pci_func);
 
-       bfa_msix_install(bfa);
-       intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-                      __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
-                      __HFN_INT_LL_HALT);
-
-       if (pci_func == 0)
-               intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
-                               __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
-                               __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
-                               __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
-                               __HFN_INT_MBOX_LPU0);
-       else
-               intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
-                               __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
-                               __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
-                               __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
-                               __HFN_INT_MBOX_LPU1);
-
-       writel(intr_unmask, bfa->iocfc.bfa_regs.intr_status);
-       writel(~intr_unmask, bfa->iocfc.bfa_regs.intr_mask);
-       bfa->iocfc.intr_mask = ~intr_unmask;
+       bfa_msix_ctrl_install(bfa);
+
+       if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
+               umsk = __HFN_INT_ERR_MASK_CT2;
+               umsk |= pci_func == 0 ?
+                       __HFN_INT_FN0_MASK_CT2 : __HFN_INT_FN1_MASK_CT2;
+       } else {
+               umsk = __HFN_INT_ERR_MASK;
+               umsk |= pci_func == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK;
+       }
+
+       writel(umsk, bfa->iocfc.bfa_regs.intr_status);
+       writel(~umsk, bfa->iocfc.bfa_regs.intr_mask);
+       bfa->iocfc.intr_mask = ~umsk;
        bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
 }
 
@@ -263,20 +396,9 @@ bfa_isr_disable(struct bfa_s *bfa)
 }
 
 void
-bfa_msix_reqq(struct bfa_s *bfa, int qid)
+bfa_msix_reqq(struct bfa_s *bfa, int vec)
 {
-       struct list_head *waitq;
-
-       qid &= (BFI_IOC_MAX_CQS - 1);
-
-       bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
-
-       /*
-        * Resume any pending requests in the corresponding reqq.
-        */
-       waitq = bfa_reqq(bfa, qid);
-       if (!list_empty(waitq))
-               bfa_reqq_resume(bfa, qid);
+       bfa_isr_reqq(bfa, vec - bfa->iocfc.hwif.cpe_vec_q0);
 }
 
 void
@@ -290,57 +412,37 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
 }
 
 void
-bfa_msix_rspq(struct bfa_s *bfa, int qid)
+bfa_msix_rspq(struct bfa_s *bfa, int vec)
 {
-       struct bfi_msg_s *m;
-       u32 pi, ci;
-       struct list_head *waitq;
-
-       qid &= (BFI_IOC_MAX_CQS - 1);
-
-       bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
-
-       ci = bfa_rspq_ci(bfa, qid);
-       pi = bfa_rspq_pi(bfa, qid);
-
-       if (bfa->rme_process) {
-               while (ci != pi) {
-                       m = bfa_rspq_elem(bfa, qid, ci);
-                       bfa_isrs[m->mhdr.msg_class] (bfa, m);
-                       CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
-               }
-       }
-
-       /*
-        * update CI
-        */
-       bfa_rspq_ci(bfa, qid) = pi;
-       writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
-       mmiowb();
-
-       /*
-        * Resume any pending requests in the corresponding reqq.
-        */
-       waitq = bfa_reqq(bfa, qid);
-       if (!list_empty(waitq))
-               bfa_reqq_resume(bfa, qid);
+       bfa_isr_rspq(bfa, vec - bfa->iocfc.hwif.rme_vec_q0);
 }
 
 void
 bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
 {
        u32 intr, curr_value;
+       bfa_boolean_t lpu_isr, halt_isr, pss_isr;
 
        intr = readl(bfa->iocfc.bfa_regs.intr_status);
 
-       if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
-               bfa_ioc_mbox_isr(&bfa->ioc);
+       if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
+               halt_isr = intr & __HFN_INT_CPQ_HALT_CT2;
+               pss_isr  = intr & __HFN_INT_ERR_PSS_CT2;
+               lpu_isr  = intr & (__HFN_INT_MBOX_LPU0_CT2 |
+                                  __HFN_INT_MBOX_LPU1_CT2);
+               intr    &= __HFN_INT_ERR_MASK_CT2;
+       } else {
+               halt_isr = intr & __HFN_INT_LL_HALT;
+               pss_isr  = intr & __HFN_INT_ERR_PSS;
+               lpu_isr  = intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1);
+               intr    &= __HFN_INT_ERR_MASK;
+       }
 
-       intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-               __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
+       if (lpu_isr)
+               bfa_ioc_mbox_isr(&bfa->ioc);
 
        if (intr) {
-               if (intr & __HFN_INT_LL_HALT) {
+               if (halt_isr) {
                        /*
                         * If LL_HALT bit is set then FW Init Halt LL Port
                         * Register needs to be cleared as well so Interrupt
@@ -351,7 +453,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
                        writel(curr_value, bfa->ioc.ioc_regs.ll_halt);
                }
 
-               if (intr & __HFN_INT_ERR_PSS) {
+               if (pss_isr) {
                        /*
                         * ERR_PSS bit needs to be cleared as well in case
                         * interrups are shared so driver's interrupt handler is
@@ -359,7 +461,6 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
                         */
                        curr_value = readl(
                                        bfa->ioc.ioc_regs.pss_err_status_reg);
-                       curr_value &= __PSS_ERR_STATUS_SET;
                        writel(curr_value,
                                bfa->ioc.ioc_regs.pss_err_status_reg);
                }
@@ -377,41 +478,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
  */
@@ -433,8 +499,13 @@ bfa_iocfc_send_cfg(void *bfa_arg)
        /*
         * initialize IOC configuration info
         */
+       cfg_info->single_msix_vec = 0;
+       if (bfa->msix.nvecs == 1)
+               cfg_info->single_msix_vec = 1;
        cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
        cfg_info->num_cqs = cfg->fwcfg.num_cqs;
+       cfg_info->num_ioim_reqs = cpu_to_be16(cfg->fwcfg.num_ioim_reqs);
+       cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);
 
        bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
        /*
@@ -469,7 +540,7 @@ bfa_iocfc_send_cfg(void *bfa_arg)
         * dma map IOC configuration itself
         */
        bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
-                   bfa_lpuid(bfa));
+                   bfa_fn_lpu(bfa));
        bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
 
        bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
@@ -491,26 +562,40 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        /*
         * Initialize chip specific handlers.
         */
-       if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
+       if (bfa_asic_id_ctc(bfa_ioc_devid(&bfa->ioc))) {
                iocfc->hwif.hw_reginit = bfa_hwct_reginit;
                iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
                iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
                iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
-               iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
+               iocfc->hwif.hw_msix_ctrl_install = bfa_hwct_msix_ctrl_install;
+               iocfc->hwif.hw_msix_queue_install = bfa_hwct_msix_queue_install;
                iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
                iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
                iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
                iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
+               iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CT;
+               iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CT;
        } else {
                iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
-               iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
-               iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+               iocfc->hwif.hw_reqq_ack = NULL;
+               iocfc->hwif.hw_rspq_ack = NULL;
                iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
-               iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
+               iocfc->hwif.hw_msix_ctrl_install = bfa_hwcb_msix_ctrl_install;
+               iocfc->hwif.hw_msix_queue_install = bfa_hwcb_msix_queue_install;
                iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
                iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
                iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
                iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
+               iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CB +
+                       bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
+               iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CB +
+                       bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
+       }
+
+       if (bfa_asic_id_ct2(bfa_ioc_devid(&bfa->ioc))) {
+               iocfc->hwif.hw_reginit = bfa_hwct2_reginit;
+               iocfc->hwif.hw_isr_mode_set = NULL;
+               iocfc->hwif.hw_rspq_ack = NULL;
        }
 
        iocfc->hwif.hw_reginit(bfa);
@@ -518,48 +603,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;
-
-       dm_kva = bfa_meminfo_dma_virt(meminfo);
-       dm_pa = bfa_meminfo_dma_phys(meminfo);
+       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;
 
-       /*
-        * 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;
@@ -572,36 +651,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;
        }
 }
 
@@ -613,7 +683,9 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
 {
        int             i;
 
-       bfa->rme_process = BFA_TRUE;
+       bfa->queue_process = BFA_TRUE;
+       for (i = 0; i < BFI_IOC_MAX_CQS; i++)
+               bfa_isr_rspq_ack(bfa, i);
 
        for (i = 0; hal_mods[i]; i++)
                hal_mods[i]->start(bfa);
@@ -660,6 +732,16 @@ bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
 }
 
 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)
 {
        struct bfa_s  *bfa = bfa_arg;
@@ -669,6 +751,37 @@ bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
                complete(&bfad->disable_comp);
 }
 
+/**
+ * configure queue registers from firmware response
+ */
+static void
+bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg)
+{
+       int     i;
+       struct bfa_iocfc_regs_s *r = &bfa->iocfc.bfa_regs;
+       void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
+
+       for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
+               bfa->iocfc.hw_qid[i] = qreg->hw_qid[i];
+               r->cpe_q_ci[i] = kva + be32_to_cpu(qreg->cpe_q_ci_off[i]);
+               r->cpe_q_pi[i] = kva + be32_to_cpu(qreg->cpe_q_pi_off[i]);
+               r->cpe_q_ctrl[i] = kva + be32_to_cpu(qreg->cpe_qctl_off[i]);
+               r->rme_q_ci[i] = kva + be32_to_cpu(qreg->rme_q_ci_off[i]);
+               r->rme_q_pi[i] = kva + be32_to_cpu(qreg->rme_q_pi_off[i]);
+               r->rme_q_ctrl[i] = kva + be32_to_cpu(qreg->rme_qctl_off[i]);
+       }
+}
+
+static void
+bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg)
+{
+       bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs);
+       bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs);
+       bfa_rport_res_recfg(bfa, fwcfg->num_rports);
+       bfa_fcp_res_recfg(bfa, fwcfg->num_ioim_reqs);
+       bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs);
+}
+
 /*
  * Update BFA configuration from firmware configuration.
  */
@@ -681,6 +794,7 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
 
        fwcfg->num_cqs        = fwcfg->num_cqs;
        fwcfg->num_ioim_reqs  = be16_to_cpu(fwcfg->num_ioim_reqs);
+       fwcfg->num_fwtio_reqs = be16_to_cpu(fwcfg->num_fwtio_reqs);
        fwcfg->num_tskim_reqs = be16_to_cpu(fwcfg->num_tskim_reqs);
        fwcfg->num_fcxp_reqs  = be16_to_cpu(fwcfg->num_fcxp_reqs);
        fwcfg->num_uf_bufs    = be16_to_cpu(fwcfg->num_uf_bufs);
@@ -689,14 +803,33 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
        iocfc->cfgdone = BFA_TRUE;
 
        /*
+        * configure queue register offsets as learnt from firmware
+        */
+       bfa_iocfc_qreg(bfa, &cfgrsp->qreg);
+
+       /*
+        * Re-configure resources as learnt from Firmware
+        */
+       bfa_iocfc_res_recfg(bfa, fwcfg);
+
+       /*
+        * Install MSIX queue handlers
+        */
+       bfa_msix_queue_install(bfa);
+
+       /*
         * Configuration is complete - initialize/start submodules
         */
        bfa_fcport_init(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)
@@ -711,6 +844,181 @@ bfa_iocfc_reset_queues(struct bfa_s *bfa)
        }
 }
 
+/* Fabric Assigned Address specific functions */
+
+/*
+ *     Check whether IOC is ready before sending command down
+ */
+static bfa_status_t
+bfa_faa_validate_request(struct bfa_s *bfa)
+{
+       enum bfa_ioc_type_e     ioc_type = bfa_get_type(bfa);
+       u32     card_type = bfa->ioc.attr->card_type;
+
+       if (bfa_ioc_is_operational(&bfa->ioc)) {
+               if ((ioc_type != BFA_IOC_TYPE_FC) || bfa_mfg_is_mezz(card_type))
+                       return BFA_STATUS_FEATURE_NOT_SUPPORTED;
+       } else {
+               if (!bfa_ioc_is_acq_addr(&bfa->ioc))
+                       return BFA_STATUS_IOC_NON_OP;
+       }
+
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_enable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn, void *cbarg)
+{
+       struct bfi_faa_en_dis_s faa_enable_req;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+       bfa_status_t            status;
+
+       iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+       iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+       status = bfa_faa_validate_request(bfa);
+       if (status != BFA_STATUS_OK)
+               return status;
+
+       if (iocfc->faa_args.busy == BFA_TRUE)
+               return BFA_STATUS_DEVBUSY;
+
+       if (iocfc->faa_args.faa_state == BFA_FAA_ENABLED)
+               return BFA_STATUS_FAA_ENABLED;
+
+       if (bfa_fcport_is_trunk_enabled(bfa))
+               return BFA_STATUS_ERROR_TRUNK_ENABLED;
+
+       bfa_fcport_cfg_faa(bfa, BFA_FAA_ENABLED);
+       iocfc->faa_args.busy = BFA_TRUE;
+
+       memset(&faa_enable_req, 0, sizeof(struct bfi_faa_en_dis_s));
+       bfi_h2i_set(faa_enable_req.mh, BFI_MC_IOCFC,
+               BFI_IOCFC_H2I_FAA_ENABLE_REQ, bfa_fn_lpu(bfa));
+
+       bfa_ioc_mbox_send(&bfa->ioc, &faa_enable_req,
+                       sizeof(struct bfi_faa_en_dis_s));
+
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_disable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn,
+               void *cbarg)
+{
+       struct bfi_faa_en_dis_s faa_disable_req;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+       bfa_status_t            status;
+
+       iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+       iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+       status = bfa_faa_validate_request(bfa);
+       if (status != BFA_STATUS_OK)
+               return status;
+
+       if (iocfc->faa_args.busy == BFA_TRUE)
+               return BFA_STATUS_DEVBUSY;
+
+       if (iocfc->faa_args.faa_state == BFA_FAA_DISABLED)
+               return BFA_STATUS_FAA_DISABLED;
+
+       bfa_fcport_cfg_faa(bfa, BFA_FAA_DISABLED);
+       iocfc->faa_args.busy = BFA_TRUE;
+
+       memset(&faa_disable_req, 0, sizeof(struct bfi_faa_en_dis_s));
+       bfi_h2i_set(faa_disable_req.mh, BFI_MC_IOCFC,
+               BFI_IOCFC_H2I_FAA_DISABLE_REQ, bfa_fn_lpu(bfa));
+
+       bfa_ioc_mbox_send(&bfa->ioc, &faa_disable_req,
+               sizeof(struct bfi_faa_en_dis_s));
+
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
+               bfa_cb_iocfc_t cbfn, void *cbarg)
+{
+       struct bfi_faa_query_s  faa_attr_req;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+       bfa_status_t            status;
+
+       iocfc->faa_args.faa_attr = attr;
+       iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+       iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+       status = bfa_faa_validate_request(bfa);
+       if (status != BFA_STATUS_OK)
+               return status;
+
+       if (iocfc->faa_args.busy == BFA_TRUE)
+               return BFA_STATUS_DEVBUSY;
+
+       iocfc->faa_args.busy = BFA_TRUE;
+       memset(&faa_attr_req, 0, sizeof(struct bfi_faa_query_s));
+       bfi_h2i_set(faa_attr_req.mh, BFI_MC_IOCFC,
+               BFI_IOCFC_H2I_FAA_QUERY_REQ, bfa_fn_lpu(bfa));
+
+       bfa_ioc_mbox_send(&bfa->ioc, &faa_attr_req,
+               sizeof(struct bfi_faa_query_s));
+
+       return BFA_STATUS_OK;
+}
+
+/*
+ *     FAA enable response
+ */
+static void
+bfa_faa_enable_reply(struct bfa_iocfc_s *iocfc,
+               struct bfi_faa_en_dis_rsp_s *rsp)
+{
+       void    *cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+       bfa_status_t    status = rsp->status;
+
+       WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+       iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
+       iocfc->faa_args.busy = BFA_FALSE;
+}
+
+/*
+ *     FAA disable response
+ */
+static void
+bfa_faa_disable_reply(struct bfa_iocfc_s *iocfc,
+               struct bfi_faa_en_dis_rsp_s *rsp)
+{
+       void    *cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+       bfa_status_t    status = rsp->status;
+
+       WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+       iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
+       iocfc->faa_args.busy = BFA_FALSE;
+}
+
+/*
+ *     FAA query response
+ */
+static void
+bfa_faa_query_reply(struct bfa_iocfc_s *iocfc,
+               bfi_faa_query_rsp_t *rsp)
+{
+       void    *cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+
+       if (iocfc->faa_args.faa_attr) {
+               iocfc->faa_args.faa_attr->faa = rsp->faa;
+               iocfc->faa_args.faa_attr->faa_state = rsp->faa_status;
+               iocfc->faa_args.faa_attr->pwwn_source = rsp->addr_source;
+       }
+
+       WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+       iocfc->faa_args.faa_cb.faa_cbfn(cbarg, BFA_STATUS_OK);
+       iocfc->faa_args.busy = BFA_FALSE;
+}
+
 /*
  * IOC enable request is complete
  */
@@ -719,11 +1027,20 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
 {
        struct bfa_s    *bfa = bfa_arg;
 
+       if (status == BFA_STATUS_FAA_ACQ_ADDR) {
+               bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+                               bfa_iocfc_init_cb, bfa);
+               return;
+       }
+
        if (status != BFA_STATUS_OK) {
                bfa_isr_disable(bfa);
                if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
                        bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
                                     bfa_iocfc_init_cb, bfa);
+               else if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
+                       bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
+                                       bfa_iocfc_enable_cb, bfa);
                return;
        }
 
@@ -759,7 +1076,7 @@ bfa_iocfc_hbfail_cbfn(void *bfa_arg)
 {
        struct bfa_s    *bfa = bfa_arg;
 
-       bfa->rme_process = BFA_FALSE;
+       bfa->queue_process = BFA_FALSE;
 
        bfa_isr_disable(bfa);
        bfa_iocfc_disable_submod(bfa);
@@ -786,15 +1103,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);
 
-       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;
+       /* dma memory setup for IOCFC */
+       bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len);
+
+       /* kva memory setup for IOCFC */
+       bfa_mem_kva_setup(meminfo, iocfc_kva,
+                       ((bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0));
 }
 
 /*
@@ -802,7 +1151,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;
@@ -815,17 +1164,11 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
        ioc->trcmod = bfa->trcmod;
        bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod);
 
-       /*
-        * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
-        */
-       if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
-               bfa_ioc_set_fcmode(&bfa->ioc);
-
-       bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
+       bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_PCIFN_CLASS_FC);
        bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
 
        bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
-       bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+       bfa_iocfc_mem_claim(bfa, cfg);
        INIT_LIST_HEAD(&bfa->timer_mod.timer_q);
 
        INIT_LIST_HEAD(&bfa->comp_q);
@@ -863,7 +1206,7 @@ bfa_iocfc_stop(struct bfa_s *bfa)
 {
        bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
 
-       bfa->rme_process = BFA_FALSE;
+       bfa->queue_process = BFA_FALSE;
        bfa_ioc_disable(&bfa->ioc);
 }
 
@@ -879,12 +1222,22 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
 
        switch (msg->mh.msg_id) {
        case BFI_IOCFC_I2H_CFG_REPLY:
-               iocfc->cfg_reply = &msg->cfg_reply;
                bfa_iocfc_cfgrsp(bfa);
                break;
        case BFI_IOCFC_I2H_UPDATEQ_RSP:
                iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
                break;
+       case BFI_IOCFC_I2H_FAA_ENABLE_RSP:
+               bfa_faa_enable_reply(iocfc,
+                       (struct bfi_faa_en_dis_rsp_s *)msg);
+               break;
+       case BFI_IOCFC_I2H_FAA_DISABLE_RSP:
+               bfa_faa_disable_reply(iocfc,
+                       (struct bfi_faa_en_dis_rsp_s *)msg);
+               break;
+       case BFI_IOCFC_I2H_FAA_QUERY_RSP:
+               bfa_faa_query_reply(iocfc, (bfi_faa_query_rsp_t *)msg);
+               break;
        default:
                WARN_ON(1);
        }
@@ -926,7 +1279,7 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
                return BFA_STATUS_DEVBUSY;
 
        bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
-                   bfa_lpuid(bfa));
+                   bfa_fn_lpu(bfa));
        m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
        m->delay    = iocfc->cfginfo->intr_attr.delay;
        m->latency  = iocfc->cfginfo->intr_attr.latency;
@@ -934,17 +1287,17 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
        bfa_trc(bfa, attr->delay);
        bfa_trc(bfa, attr->latency);
 
-       bfa_reqq_produce(bfa, BFA_REQQ_IOC);
+       bfa_reqq_produce(bfa, BFA_REQQ_IOC, m->mh);
        return BFA_STATUS_OK;
 }
 
 void
-bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa)
 {
        struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
 
        iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
-       bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+       bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase[seg_no], snsbase_pa);
 }
 /*
  * Enable IOC after it is disabled.
@@ -954,6 +1307,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);
 }
 
@@ -964,7 +1318,7 @@ bfa_iocfc_disable(struct bfa_s *bfa)
                     "IOC Disable");
        bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
 
-       bfa->rme_process = BFA_FALSE;
+       bfa->queue_process = BFA_FALSE;
        bfa_ioc_disable(&bfa->ioc);
 }
 
@@ -1033,33 +1387,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();
+       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));
 }
 
 /*
@@ -1092,28 +1462,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;
+       }
+
+       list_for_each(km_qe, &kva_info->qe) {
+               kva_elem = (struct bfa_mem_kva_s *) km_qe;
+               kva_elem->kva_curp = kva_elem->kva;
        }
 
-       bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev);
+       bfa_iocfc_attach(bfa, bfad, cfg, pcidev);
 
        for (i = 0; hal_mods[i]; i++)
-               hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
-
-       bfa_com_port_attach(bfa, meminfo);
+               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);
 }
 
 /*
@@ -1215,6 +1603,7 @@ bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
        cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS;
        cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS;
        cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS;
+       cfg->fwcfg.num_fwtio_reqs = 0;
 
        cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS;
        cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS;
@@ -1236,6 +1625,7 @@ bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)
        cfg->fwcfg.num_fcxp_reqs   = BFA_FCXP_MIN;
        cfg->fwcfg.num_uf_bufs     = BFA_UF_MIN;
        cfg->fwcfg.num_rports      = BFA_RPORT_MIN;
+       cfg->fwcfg.num_fwtio_reqs = 0;
 
        cfg->drvcfg.num_sgpgs      = BFA_SGPG_MIN;
        cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
index d85f93a..ed8d31b 100644 (file)
@@ -40,7 +40,12 @@ enum {
        BFA_MFG_TYPE_ASTRA    = 807,     /*  Astra mezz card            */
        BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*  Lightning mezz card - old  */
        BFA_MFG_TYPE_LIGHTNING = 1741,   /*  Lightning mezz card        */
-       BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type          */
+       BFA_MFG_TYPE_PROWLER_F = 1560,   /*  Prowler FC only cards      */
+       BFA_MFG_TYPE_PROWLER_N = 1410,   /*  Prowler NIC only cards     */
+       BFA_MFG_TYPE_PROWLER_C = 1710,   /*  Prowler CNA only cards     */
+       BFA_MFG_TYPE_PROWLER_D = 1860,   /*  Prowler Dual cards         */
+       BFA_MFG_TYPE_CHINOOK   = 1867,   /*  Chinook cards              */
+       BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type          */
 };
 
 #pragma pack(1)
@@ -53,7 +58,8 @@ enum {
        (type) == BFA_MFG_TYPE_WANCHESE || \
        (type) == BFA_MFG_TYPE_ASTRA || \
        (type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
-       (type) == BFA_MFG_TYPE_LIGHTNING))
+       (type) == BFA_MFG_TYPE_LIGHTNING || \
+       (type) == BFA_MFG_TYPE_CHINOOK))
 
 /*
  * Check if the card having old wwn/mac handling
@@ -124,30 +130,53 @@ enum bfa_status {
        BFA_STATUS_ETIMER       = 5,    /*  Timer expired - Retry, if persists,
                                         *  contact support */
        BFA_STATUS_EPROTOCOL    = 6,    /*  Protocol error */
+       BFA_STATUS_SFP_UNSUPP   = 10,   /*  Unsupported SFP - Replace SFP */
+       BFA_STATUS_UNKNOWN_VFID = 11,   /*  VF_ID not found */
+       BFA_STATUS_DATACORRUPTED = 12,  /*  Diag returned data corrupted */
        BFA_STATUS_DEVBUSY      = 13,   /*  Device busy - Retry operation */
+       BFA_STATUS_HDMA_FAILED  = 16,   /* Host dma failed contact support */
+       BFA_STATUS_FLASH_BAD_LEN = 17,  /*  Flash bad length */
        BFA_STATUS_UNKNOWN_LWWN = 18,   /*  LPORT PWWN not found */
        BFA_STATUS_UNKNOWN_RWWN = 19,   /*  RPORT PWWN not found */
        BFA_STATUS_VPORT_EXISTS = 21,   /*  VPORT already exists */
        BFA_STATUS_VPORT_MAX    = 22,   /*  Reached max VPORT supported limit */
        BFA_STATUS_UNSUPP_SPEED = 23,   /*  Invalid Speed Check speed setting */
        BFA_STATUS_INVLD_DFSZ   = 24,   /*  Invalid Max data field size */
+       BFA_STATUS_CMD_NOTSUPP  = 26,   /*  Command/API not supported */
        BFA_STATUS_FABRIC_RJT   = 29,   /*  Reject from attached fabric */
+       BFA_STATUS_PORT_OFFLINE = 34,   /*  Port is not online */
        BFA_STATUS_VPORT_WWN_BP = 46,   /*  WWN is same as base port's WWN */
+       BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port */
        BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the rport */
        BFA_STATUS_IOC_FAILURE  = 56,   /* IOC failure - Retry, if persists
                                         * contact support */
        BFA_STATUS_INVALID_WWN  = 57,   /*  Invalid WWN */
+       BFA_STATUS_ADAPTER_ENABLED = 60, /* Adapter is not disabled */
+       BFA_STATUS_IOC_NON_OP   = 61,   /* IOC is not operational */
+       BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */
        BFA_STATUS_DIAG_BUSY    = 71,   /*  diag busy */
+       BFA_STATUS_BEACON_ON    = 72,   /* Port Beacon already on */
        BFA_STATUS_ENOFSAVE     = 78,   /*  No saved firmware trace */
        BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */
+       BFA_STATUS_NO_SFP_DEV = 89,     /* No SFP device check or replace SFP */
+       BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
+       BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
        BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
        BFA_STATUS_PBC          = 154, /*  Operation not allowed for pre-boot
                                        *  configuration */
+       BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */
        BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
                                         * this adapter */
        BFA_STATUS_TRUNK_DISABLED  = 165, /* Trunking is disabled on
                                           * the adapter */
        BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
+       BFA_STATUS_PHY_NOT_PRESENT = 183, /* PHY module not present */
+       BFA_STATUS_FEATURE_NOT_SUPPORTED = 192, /* Feature not supported */
+       BFA_STATUS_FAA_ENABLED = 197,   /* FAA is already enabled */
+       BFA_STATUS_FAA_DISABLED = 198,  /* FAA is already disabled */
+       BFA_STATUS_FAA_ACQUIRED = 199,  /* FAA is already acquired */
+       BFA_STATUS_FAA_ACQ_ADDR = 200,  /* Acquiring addr */
+       BFA_STATUS_ERROR_TRUNK_ENABLED = 203,   /* Trunk enabled on adapter */
        BFA_STATUS_MAX_VAL              /* Unknown error code */
 };
 #define bfa_status_t enum bfa_status
@@ -265,6 +294,8 @@ enum bfa_ioc_state {
        BFA_IOC_DISABLED        = 10,   /*  IOC is disabled */
        BFA_IOC_FWMISMATCH      = 11,   /*  IOC f/w different from drivers */
        BFA_IOC_ENABLING        = 12,   /*  IOC is being enabled */
+       BFA_IOC_HWFAIL          = 13,   /*  PCI mapping doesn't exist */
+       BFA_IOC_ACQ_ADDR        = 14,   /*  Acquiring addr from fabric */
 };
 
 /*
@@ -294,6 +325,7 @@ struct bfa_ioc_drv_stats_s {
        u32     enable_reqs;
        u32     disable_replies;
        u32     enable_replies;
+       u32     rsvd;
 };
 
 /*
@@ -320,7 +352,10 @@ struct bfa_ioc_attr_s {
        struct bfa_ioc_driver_attr_s    driver_attr;    /*  driver attr    */
        struct bfa_ioc_pci_attr_s       pci_attr;
        u8                              port_id;        /*  port number    */
-       u8                              rsvd[7];        /*  64bit align    */
+       u8                              port_mode;      /*  bfa_mode_s  */
+       u8                              cap_bm;         /*  capability  */
+       u8                              port_mode_cfg;  /*  bfa_mode_s  */
+       u8                              rsvd[4];        /*  64bit align */
 };
 
 /*
@@ -337,6 +372,21 @@ struct bfa_ioc_attr_s {
 #define BFA_MFG_SUPPLIER_PARTNUM_SIZE          20
 #define BFA_MFG_SUPPLIER_SERIALNUM_SIZE                20
 #define BFA_MFG_SUPPLIER_REVISION_SIZE         4
+/*
+ * Initial capability definition
+ */
+#define BFA_MFG_IC_FC  0x01
+#define BFA_MFG_IC_ETH 0x02
+
+/*
+ * Adapter capability mask definition
+ */
+#define BFA_CM_HBA     0x01
+#define BFA_CM_CNA     0x02
+#define BFA_CM_NIC     0x04
+#define BFA_CM_FC16G   0x08
+#define BFA_CM_SRIOV   0x10
+#define BFA_CM_MEZZ    0x20
 
 #pragma pack(1)
 
@@ -344,31 +394,39 @@ struct bfa_ioc_attr_s {
  * All numerical fields are in big-endian format.
  */
 struct bfa_mfg_block_s {
-       u8              version;        /*  manufacturing block version */
-       u8              mfg_sig[3];     /*  characters 'M', 'F', 'G' */
-       u16     mfgsize;        /*  mfg block size */
-       u16     u16_chksum;     /*  old u16 checksum */
-       char            brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
-       char            brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
-       u8              mfg_day;        /*  manufacturing day */
-       u8              mfg_month;      /*  manufacturing month */
-       u16     mfg_year;       /*  manufacturing year */
-       wwn_t           mfg_wwn;        /*  wwn base for this adapter */
-       u8              num_wwn;        /*  number of wwns assigned */
-       u8              mfg_speeds;     /*  speeds allowed for this adapter */
-       u8              rsv[2];
-       char            supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
-       char            supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
-       char
-               supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
-       char
-               supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
-       mac_t           mfg_mac;        /*  mac address */
-       u8              num_mac;        /*  number of mac addresses */
-       u8              rsv2;
-       u32     mfg_type;       /*  card type */
-       u8              rsv3[108];
-       u8              md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*  md5 checksum */
+       u8      version;    /*!< manufacturing block version */
+       u8     mfg_sig[3]; /*!< characters 'M', 'F', 'G' */
+       u16    mfgsize;    /*!< mfg block size */
+       u16    u16_chksum; /*!< old u16 checksum */
+       char        brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+       char        brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+       u8     mfg_day;    /*!< manufacturing day */
+       u8     mfg_month;  /*!< manufacturing month */
+       u16    mfg_year;   /*!< manufacturing year */
+       wwn_t       mfg_wwn;    /*!< wwn base for this adapter */
+       u8     num_wwn;    /*!< number of wwns assigned */
+       u8     mfg_speeds; /*!< speeds allowed for this adapter */
+       u8     rsv[2];
+       char    supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+       char    supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+       char    supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+       char    supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+       mac_t       mfg_mac;    /*!< base mac address */
+       u8     num_mac;    /*!< number of mac addresses */
+       u8     rsv2;
+       u32    card_type;  /*!< card type          */
+       char        cap_nic;    /*!< capability nic     */
+       char        cap_cna;    /*!< capability cna     */
+       char        cap_hba;    /*!< capability hba     */
+       char        cap_fc16g;  /*!< capability fc 16g      */
+       char        cap_sriov;  /*!< capability sriov       */
+       char        cap_mezz;   /*!< capability mezz        */
+       u8     rsv3;
+       u8     mfg_nports; /*!< number of ports        */
+       char        media[8];   /*!< xfi/xaui           */
+       char        initial_mode[8]; /*!< initial mode: hba/cna/nic */
+       u8     rsv4[84];
+       u8     md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
 };
 
 #pragma pack()
@@ -386,17 +444,27 @@ enum {
        BFA_PCI_DEVICE_ID_FC_8G1P       = 0x17,
        BFA_PCI_DEVICE_ID_CT            = 0x14,
        BFA_PCI_DEVICE_ID_CT_FC         = 0x21,
+       BFA_PCI_DEVICE_ID_CT2           = 0x22,
 };
 
-#define bfa_asic_id_ct(devid)                  \
-       ((devid) == BFA_PCI_DEVICE_ID_CT ||     \
-        (devid) == BFA_PCI_DEVICE_ID_CT_FC)
+#define bfa_asic_id_cb(__d)                    \
+       ((__d) == BFA_PCI_DEVICE_ID_FC_8G2P ||  \
+        (__d) == BFA_PCI_DEVICE_ID_FC_8G1P)
+#define bfa_asic_id_ct(__d)                    \
+       ((__d) == BFA_PCI_DEVICE_ID_CT ||       \
+        (__d) == BFA_PCI_DEVICE_ID_CT_FC)
+#define bfa_asic_id_ct2(__d)   ((__d) == BFA_PCI_DEVICE_ID_CT2)
+#define bfa_asic_id_ctc(__d)   \
+       (bfa_asic_id_ct(__d) || bfa_asic_id_ct2(__d))
 
 /*
  * PCI sub-system device and vendor ID information
  */
 enum {
        BFA_PCI_FCOE_SSDEVICE_ID        = 0x14,
+       BFA_PCI_CT2_SSID_FCoE           = 0x22,
+       BFA_PCI_CT2_SSID_ETH            = 0x23,
+       BFA_PCI_CT2_SSID_FC             = 0x24,
 };
 
 /*
@@ -416,9 +484,7 @@ enum bfa_port_speed {
        BFA_PORT_SPEED_8GBPS    = 8,
        BFA_PORT_SPEED_10GBPS   = 10,
        BFA_PORT_SPEED_16GBPS   = 16,
-       BFA_PORT_SPEED_AUTO =
-               (BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
-                BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS),
+       BFA_PORT_SPEED_AUTO     = 0xf,
 };
 #define bfa_port_speed_t enum bfa_port_speed
 
@@ -463,4 +529,453 @@ struct bfa_boot_pbc_s {
        struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
 };
 
+/*
+ * ASIC block configuration related structures
+ */
+#define BFA_ABLK_MAX_PORTS     2
+#define BFA_ABLK_MAX_PFS       16
+#define BFA_ABLK_MAX           2
+
+#pragma pack(1)
+enum bfa_mode_s {
+       BFA_MODE_HBA    = 1,
+       BFA_MODE_CNA    = 2,
+       BFA_MODE_NIC    = 3
+};
+
+struct bfa_adapter_cfg_mode_s {
+       u16     max_pf;
+       u16     max_vf;
+       enum bfa_mode_s mode;
+};
+
+struct bfa_ablk_cfg_pf_s {
+       u16     pers;
+       u8      port_id;
+       u8      optrom;
+       u8      valid;
+       u8      sriov;
+       u8      max_vfs;
+       u8      rsvd[1];
+       u16     num_qpairs;
+       u16     num_vectors;
+       u32     bw;
+};
+
+struct bfa_ablk_cfg_port_s {
+       u8      mode;
+       u8      type;
+       u8      max_pfs;
+       u8      rsvd[5];
+};
+
+struct bfa_ablk_cfg_inst_s {
+       u8      nports;
+       u8      max_pfs;
+       u8      rsvd[6];
+       struct bfa_ablk_cfg_pf_s        pf_cfg[BFA_ABLK_MAX_PFS];
+       struct bfa_ablk_cfg_port_s      port_cfg[BFA_ABLK_MAX_PORTS];
+};
+
+struct bfa_ablk_cfg_s {
+       struct bfa_ablk_cfg_inst_s      inst[BFA_ABLK_MAX];
+};
+
+
+/*
+ *     SFP module specific
+ */
+#define SFP_DIAGMON_SIZE       10 /* num bytes of diag monitor data */
+
+enum bfa_defs_sfp_media_e {
+       BFA_SFP_MEDIA_UNKNOWN   = 0x00,
+       BFA_SFP_MEDIA_CU        = 0x01,
+       BFA_SFP_MEDIA_LW        = 0x02,
+       BFA_SFP_MEDIA_SW        = 0x03,
+       BFA_SFP_MEDIA_EL        = 0x04,
+       BFA_SFP_MEDIA_UNSUPPORT = 0x05,
+};
+
+/*
+ * values for xmtr_tech above
+ */
+enum {
+       SFP_XMTR_TECH_CU = (1 << 0),    /* copper FC-BaseT */
+       SFP_XMTR_TECH_CP = (1 << 1),    /* copper passive */
+       SFP_XMTR_TECH_CA = (1 << 2),    /* copper active */
+       SFP_XMTR_TECH_LL = (1 << 3),    /* longwave laser */
+       SFP_XMTR_TECH_SL = (1 << 4),    /* shortwave laser w/ OFC */
+       SFP_XMTR_TECH_SN = (1 << 5),    /* shortwave laser w/o OFC */
+       SFP_XMTR_TECH_EL_INTRA = (1 << 6), /* elec intra-enclosure */
+       SFP_XMTR_TECH_EL_INTER = (1 << 7), /* elec inter-enclosure */
+       SFP_XMTR_TECH_LC = (1 << 8),    /* longwave laser */
+       SFP_XMTR_TECH_SA = (1 << 9)
+};
+
+/*
+ * Serial ID: Data Fields -- Address A0h
+ * Basic ID field total 64 bytes
+ */
+struct sfp_srlid_base_s {
+       u8      id;             /* 00: Identifier */
+       u8      extid;          /* 01: Extended Identifier */
+       u8      connector;      /* 02: Connector */
+       u8      xcvr[8];        /* 03-10: Transceiver */
+       u8      encoding;       /* 11: Encoding */
+       u8      br_norm;        /* 12: BR, Nominal */
+       u8      rate_id;        /* 13: Rate Identifier */
+       u8      len_km;         /* 14: Length single mode km */
+       u8      len_100m;       /* 15: Length single mode 100m */
+       u8      len_om2;        /* 16: Length om2 fiber 10m */
+       u8      len_om1;        /* 17: Length om1 fiber 10m */
+       u8      len_cu;         /* 18: Length copper 1m */
+       u8      len_om3;        /* 19: Length om3 fiber 10m */
+       u8      vendor_name[16];/* 20-35 */
+       u8      unalloc1;
+       u8      vendor_oui[3];  /* 37-39 */
+       u8      vendor_pn[16];  /* 40-55 */
+       u8      vendor_rev[4];  /* 56-59 */
+       u8      wavelen[2];     /* 60-61 */
+       u8      unalloc2;
+       u8      cc_base;        /* 63: check code for base id field */
+};
+
+/*
+ * Serial ID: Data Fields -- Address A0h
+ * Extended id field total 32 bytes
+ */
+struct sfp_srlid_ext_s {
+       u8      options[2];
+       u8      br_max;
+       u8      br_min;
+       u8      vendor_sn[16];
+       u8      date_code[8];
+       u8      diag_mon_type;  /* 92: Diagnostic Monitoring type */
+       u8      en_options;
+       u8      sff_8472;
+       u8      cc_ext;
+};
+
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * Diagnostic and control/status base field total 96 bytes
+ */
+struct sfp_diag_base_s {
+       /*
+        * Alarm and warning Thresholds 40 bytes
+        */
+       u8      temp_high_alarm[2]; /* 00-01 */
+       u8      temp_low_alarm[2];  /* 02-03 */
+       u8      temp_high_warning[2];   /* 04-05 */
+       u8      temp_low_warning[2];    /* 06-07 */
+
+       u8      volt_high_alarm[2]; /* 08-09 */
+       u8      volt_low_alarm[2];  /* 10-11 */
+       u8      volt_high_warning[2];   /* 12-13 */
+       u8      volt_low_warning[2];    /* 14-15 */
+
+       u8      bias_high_alarm[2]; /* 16-17 */
+       u8      bias_low_alarm[2];  /* 18-19 */
+       u8      bias_high_warning[2];   /* 20-21 */
+       u8      bias_low_warning[2];    /* 22-23 */
+
+       u8      tx_pwr_high_alarm[2];   /* 24-25 */
+       u8      tx_pwr_low_alarm[2];    /* 26-27 */
+       u8      tx_pwr_high_warning[2]; /* 28-29 */
+       u8      tx_pwr_low_warning[2];  /* 30-31 */
+
+       u8      rx_pwr_high_alarm[2];   /* 32-33 */
+       u8      rx_pwr_low_alarm[2];    /* 34-35 */
+       u8      rx_pwr_high_warning[2]; /* 36-37 */
+       u8      rx_pwr_low_warning[2];  /* 38-39 */
+
+       u8      unallocate_1[16];
+
+       /*
+        * ext_cal_const[36]
+        */
+       u8      rx_pwr[20];
+       u8      tx_i[4];
+       u8      tx_pwr[4];
+       u8      temp[4];
+       u8      volt[4];
+       u8      unallocate_2[3];
+       u8      cc_dmi;
+};
+
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * Diagnostic and control/status extended field total 24 bytes
+ */
+struct sfp_diag_ext_s {
+       u8      diag[SFP_DIAGMON_SIZE];
+       u8      unalloc1[4];
+       u8      status_ctl;
+       u8      rsvd;
+       u8      alarm_flags[2];
+       u8      unalloc2[2];
+       u8      warning_flags[2];
+       u8      ext_status_ctl[2];
+};
+
+struct sfp_mem_s {
+       struct sfp_srlid_base_s srlid_base;
+       struct sfp_srlid_ext_s  srlid_ext;
+       struct sfp_diag_base_s  diag_base;
+       struct sfp_diag_ext_s   diag_ext;
+};
+
+/*
+ * transceiver codes (SFF-8472 Rev 10.2 Table 3.5)
+ */
+union sfp_xcvr_e10g_code_u {
+       u8              b;
+       struct {
+#ifdef __BIGENDIAN
+               u8      e10g_unall:1;   /* 10G Ethernet compliance */
+               u8      e10g_lrm:1;
+               u8      e10g_lr:1;
+               u8      e10g_sr:1;
+               u8      ib_sx:1;    /* Infiniband compliance */
+               u8      ib_lx:1;
+               u8      ib_cu_a:1;
+               u8      ib_cu_p:1;
+#else
+               u8      ib_cu_p:1;
+               u8      ib_cu_a:1;
+               u8      ib_lx:1;
+               u8      ib_sx:1;    /* Infiniband compliance */
+               u8      e10g_sr:1;
+               u8      e10g_lr:1;
+               u8      e10g_lrm:1;
+               u8      e10g_unall:1;   /* 10G Ethernet compliance */
+#endif
+       } r;
+};
+
+union sfp_xcvr_so1_code_u {
+       u8              b;
+       struct {
+               u8      escon:2;    /* ESCON compliance code */
+               u8      oc192_reach:1;  /* SONET compliance code */
+               u8      so_reach:2;
+               u8      oc48_reach:3;
+       } r;
+};
+
+union sfp_xcvr_so2_code_u {
+       u8              b;
+       struct {
+               u8      reserved:1;
+               u8      oc12_reach:3;   /* OC12 reach */
+               u8      reserved1:1;
+               u8      oc3_reach:3;    /* OC3 reach */
+       } r;
+};
+
+union sfp_xcvr_eth_code_u {
+       u8              b;
+       struct {
+               u8      base_px:1;
+               u8      base_bx10:1;
+               u8      e100base_fx:1;
+               u8      e100base_lx:1;
+               u8      e1000base_t:1;
+               u8      e1000base_cx:1;
+               u8      e1000base_lx:1;
+               u8      e1000base_sx:1;
+       } r;
+};
+
+struct sfp_xcvr_fc1_code_s {
+       u8      link_len:5; /* FC link length */
+       u8      xmtr_tech2:3;
+       u8      xmtr_tech1:7;   /* FC transmitter technology */
+       u8      reserved1:1;
+};
+
+union sfp_xcvr_fc2_code_u {
+       u8              b;
+       struct {
+               u8      tw_media:1; /* twin axial pair (tw) */
+               u8      tp_media:1; /* shielded twisted pair (sp) */
+               u8      mi_media:1; /* miniature coax (mi) */
+               u8      tv_media:1; /* video coax (tv) */
+               u8      m6_media:1; /* multimode, 62.5m (m6) */
+               u8      m5_media:1; /* multimode, 50m (m5) */
+               u8      reserved:1;
+               u8      sm_media:1; /* single mode (sm) */
+       } r;
+};
+
+union sfp_xcvr_fc3_code_u {
+       u8              b;
+       struct {
+#ifdef __BIGENDIAN
+               u8      rsv4:1;
+               u8      mb800:1;    /* 800 Mbytes/sec */
+               u8      mb1600:1;   /* 1600 Mbytes/sec */
+               u8      mb400:1;    /* 400 Mbytes/sec */
+               u8      rsv2:1;
+               u8      mb200:1;    /* 200 Mbytes/sec */
+               u8      rsv1:1;
+               u8      mb100:1;    /* 100 Mbytes/sec */
+#else
+               u8      mb100:1;    /* 100 Mbytes/sec */
+               u8      rsv1:1;
+               u8      mb200:1;    /* 200 Mbytes/sec */
+               u8      rsv2:1;
+               u8      mb400:1;    /* 400 Mbytes/sec */
+               u8      mb1600:1;   /* 1600 Mbytes/sec */
+               u8      mb800:1;    /* 800 Mbytes/sec */
+               u8      rsv4:1;
+#endif
+       } r;
+};
+
+struct sfp_xcvr_s {
+       union sfp_xcvr_e10g_code_u      e10g;
+       union sfp_xcvr_so1_code_u       so1;
+       union sfp_xcvr_so2_code_u       so2;
+       union sfp_xcvr_eth_code_u       eth;
+       struct sfp_xcvr_fc1_code_s      fc1;
+       union sfp_xcvr_fc2_code_u       fc2;
+       union sfp_xcvr_fc3_code_u       fc3;
+};
+
+/*
+ *     Flash module specific
+ */
+#define BFA_FLASH_PART_ENTRY_SIZE      32      /* partition entry size */
+#define BFA_FLASH_PART_MAX             32      /* maximal # of partitions */
+
+enum bfa_flash_part_type {
+       BFA_FLASH_PART_OPTROM   = 1,    /* option rom partition */
+       BFA_FLASH_PART_FWIMG    = 2,    /* firmware image partition */
+       BFA_FLASH_PART_FWCFG    = 3,    /* firmware tuneable config */
+       BFA_FLASH_PART_DRV      = 4,    /* IOC driver config */
+       BFA_FLASH_PART_BOOT     = 5,    /* boot config */
+       BFA_FLASH_PART_ASIC     = 6,    /* asic bootstrap configuration */
+       BFA_FLASH_PART_MFG      = 7,    /* manufacturing block partition */
+       BFA_FLASH_PART_OPTROM2  = 8,    /* 2nd option rom partition */
+       BFA_FLASH_PART_VPD      = 9,    /* vpd data of OEM info */
+       BFA_FLASH_PART_PBC      = 10,   /* pre-boot config */
+       BFA_FLASH_PART_BOOTOVL  = 11,   /* boot overlay partition */
+       BFA_FLASH_PART_LOG      = 12,   /* firmware log partition */
+       BFA_FLASH_PART_PXECFG   = 13,   /* pxe boot config partition */
+       BFA_FLASH_PART_PXEOVL   = 14,   /* pxe boot overlay partition */
+       BFA_FLASH_PART_PORTCFG  = 15,   /* port cfg partition */
+       BFA_FLASH_PART_ASICBK   = 16,   /* asic backup partition */
+};
+
+/*
+ * flash partition attributes
+ */
+struct bfa_flash_part_attr_s {
+       u32     part_type;      /* partition type */
+       u32     part_instance;  /* partition instance */
+       u32     part_off;       /* partition offset */
+       u32     part_size;      /* partition size */
+       u32     part_len;       /* partition content length */
+       u32     part_status;    /* partition status */
+       char    rsv[BFA_FLASH_PART_ENTRY_SIZE - 24];
+};
+
+/*
+ * flash attributes
+ */
+struct bfa_flash_attr_s {
+       u32     status; /* flash overall status */
+       u32     npart;  /* num of partitions */
+       struct bfa_flash_part_attr_s part[BFA_FLASH_PART_MAX];
+};
+
+/*
+ *     DIAG module specific
+ */
+#define LB_PATTERN_DEFAULT     0xB5B5B5B5
+#define QTEST_CNT_DEFAULT      10
+#define QTEST_PAT_DEFAULT      LB_PATTERN_DEFAULT
+
+struct bfa_diag_memtest_s {
+       u8      algo;
+       u8      rsvd[7];
+};
+
+struct bfa_diag_memtest_result {
+       u32     status;
+       u32     addr;
+       u32     exp; /* expect value read from reg */
+       u32     act; /* actually value read */
+       u32     err_status;             /* error status reg */
+       u32     err_status1;    /* extra error info reg */
+       u32     err_addr; /* error address reg */
+       u8      algo;
+       u8      rsv[3];
+};
+
+struct bfa_diag_loopback_result_s {
+       u32     numtxmfrm;      /* no. of transmit frame */
+       u32     numosffrm;      /* no. of outstanding frame */
+       u32     numrcvfrm;      /* no. of received good frame */
+       u32     badfrminf;      /* mis-match info */
+       u32     badfrmnum;      /* mis-match fram number */
+       u8      status;         /* loopback test result */
+       u8      rsvd[3];
+};
+
+struct bfa_diag_ledtest_s {
+       u32     cmd;    /* bfa_led_op_t */
+       u32     color;  /* bfa_led_color_t */
+       u16     freq;   /* no. of blinks every 10 secs */
+       u8      led;    /* bitmap of LEDs to be tested */
+       u8      rsvd[5];
+};
+
+struct bfa_diag_loopback_s {
+       u32     loopcnt;
+       u32     pattern;
+       u8      lb_mode;    /* bfa_port_opmode_t */
+       u8      speed;      /* bfa_port_speed_t */
+       u8      rsvd[2];
+};
+
+/*
+ *     PHY module specific
+ */
+enum bfa_phy_status_e {
+       BFA_PHY_STATUS_GOOD     = 0, /* phy is good */
+       BFA_PHY_STATUS_NOT_PRESENT      = 1, /* phy does not exist */
+       BFA_PHY_STATUS_BAD      = 2, /* phy is bad */
+};
+
+/*
+ * phy attributes for phy query
+ */
+struct bfa_phy_attr_s {
+       u32     status;         /* phy present/absent status */
+       u32     length;         /* firmware length */
+       u32     fw_ver;         /* firmware version */
+       u32     an_status;      /* AN status */
+       u32     pma_pmd_status; /* PMA/PMD link status */
+       u32     pma_pmd_signal; /* PMA/PMD signal detect */
+       u32     pcs_status;     /* PCS link status */
+};
+
+/*
+ * phy stats
+ */
+struct bfa_phy_stats_s {
+       u32     status;         /* phy stats status */
+       u32     link_breaks;    /* Num of link breaks after linkup */
+       u32     pma_pmd_fault;  /* NPMA/PMD fault */
+       u32     pcs_fault;      /* PCS fault */
+       u32     speed_neg;      /* Num of speed negotiation */
+       u32     tx_eq_training; /* Num of TX EQ training */
+       u32     tx_eq_timeout;  /* Num of TX EQ timeout */
+       u32     crc_error;      /* Num of CRC errors */
+};
+
+#pragma pack()
+
 #endif /* __BFA_DEFS_H__ */
index 191d34a..3bbc583 100644 (file)
@@ -90,12 +90,14 @@ enum bfa_lport_role {
  * FCS port configuration.
  */
 struct bfa_lport_cfg_s {
-    wwn_t             pwwn;       /*  port wwn */
-    wwn_t             nwwn;       /*  node wwn */
-    struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */
-    bfa_boolean_t       preboot_vp;  /*  vport created from PBC */
-    enum bfa_lport_role     roles;      /*  FCS port roles */
-    u8      tag[16];   /*  opaque tag from application */
+       wwn_t          pwwn;       /*  port wwn */
+       wwn_t          nwwn;       /*  node wwn */
+       struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */
+       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];
 };
 
 /*
@@ -249,12 +251,13 @@ enum bfa_vport_state {
        BFA_FCS_VPORT_FDISC_SEND        = 2,
        BFA_FCS_VPORT_FDISC             = 3,
        BFA_FCS_VPORT_FDISC_RETRY       = 4,
-       BFA_FCS_VPORT_ONLINE            = 5,
-       BFA_FCS_VPORT_DELETING          = 6,
-       BFA_FCS_VPORT_CLEANUP           = 6,
-       BFA_FCS_VPORT_LOGO_SEND         = 7,
-       BFA_FCS_VPORT_LOGO              = 8,
-       BFA_FCS_VPORT_ERROR             = 9,
+       BFA_FCS_VPORT_FDISC_RSP_WAIT    = 5,
+       BFA_FCS_VPORT_ONLINE            = 6,
+       BFA_FCS_VPORT_DELETING          = 7,
+       BFA_FCS_VPORT_CLEANUP           = 8,
+       BFA_FCS_VPORT_LOGO_SEND         = 9,
+       BFA_FCS_VPORT_LOGO              = 10,
+       BFA_FCS_VPORT_ERROR             = 11,
        BFA_FCS_VPORT_MAX_STATE,
 };
 
index 207f598..0b97525 100644 (file)
@@ -47,13 +47,12 @@ struct bfa_iocfc_fwcfg_s {
        u16        num_rports;  /*  number of remote ports      */
        u16        num_ioim_reqs;       /*  number of IO reqs           */
        u16        num_tskim_reqs;      /*  task management requests    */
-       u16        num_iotm_reqs;       /*  number of TM IO reqs        */
-       u16        num_tsktm_reqs;      /*  TM task management requests*/
+       u16        num_fwtio_reqs;      /* number of TM IO reqs in FW */
        u16        num_fcxp_reqs;       /*  unassisted FC exchanges     */
        u16        num_uf_bufs; /*  unsolicited recv buffers    */
        u8              num_cqs;
        u8              fw_tick_res;    /*  FW clock resolution in ms */
-       u8              rsvd[4];
+       u8              rsvd[2];
 };
 #pragma pack()
 
@@ -66,8 +65,12 @@ struct bfa_iocfc_drvcfg_s {
        u16         ioc_recover;        /*  IOC recovery mode             */
        u16         min_cfg;    /*  minimum configuration         */
        u16        path_tov;    /*  device path timeout   */
+       u16             num_tio_reqs;   /*!< number of TM IO reqs       */
+       u8              port_mode;
+       u8              rsvd_a;
        bfa_boolean_t   delay_comp; /*  delay completion of
                                                        failed inflight IOs */
+       u16             num_ttsk_reqs;   /* TM task management requests */
        u32             rsvd;
 };
 
@@ -82,7 +85,7 @@ struct bfa_iocfc_cfg_s {
 /*
  * IOC firmware IO stats
  */
-struct bfa_fw_io_stats_s {
+struct bfa_fw_ioim_stats_s {
        u32     host_abort;             /*  IO aborted by host driver*/
        u32     host_cleanup;           /*  IO clean up by host driver */
 
@@ -152,6 +155,54 @@ struct bfa_fw_io_stats_s {
                                                 */
 };
 
+struct bfa_fw_tio_stats_s {
+       u32     tio_conf_proc;  /* TIO CONF processed */
+       u32     tio_conf_drop;      /* TIO CONF dropped */
+       u32     tio_cleanup_req;    /* TIO cleanup requested */
+       u32     tio_cleanup_comp;   /* TIO cleanup completed */
+       u32     tio_abort_rsp;      /* TIO abort response */
+       u32     tio_abort_rsp_comp; /* TIO abort rsp completed */
+       u32     tio_abts_req;       /* TIO ABTS requested */
+       u32     tio_abts_ack;       /* TIO ABTS ack-ed */
+       u32     tio_abts_ack_nocomp; /* TIO ABTS ack-ed but not completed */
+       u32     tio_abts_tmo;       /* TIO ABTS timeout */
+       u32     tio_snsdata_dma;    /* TIO sense data DMA */
+       u32     tio_rxwchan_wait; /* TIO waiting for RX wait channel */
+       u32     tio_rxwchan_avail; /* TIO RX wait channel available */
+       u32     tio_hit_bls;        /* TIO IOH BLS event */
+       u32     tio_uf_recv;        /* TIO received UF */
+       u32     tio_rd_invalid_sm; /* TIO read reqst in wrong state machine */
+       u32     tio_wr_invalid_sm;/* TIO write reqst in wrong state machine */
+
+       u32     ds_rxwchan_wait; /* DS waiting for RX wait channel */
+       u32     ds_rxwchan_avail; /* DS RX wait channel available */
+       u32     ds_unaligned_rd;    /* DS unaligned read */
+       u32     ds_rdcomp_invalid_sm; /* DS read completed in wrong state machine */
+       u32     ds_wrcomp_invalid_sm; /* DS write completed in wrong state machine */
+       u32     ds_flush_req;       /* DS flush requested */
+       u32     ds_flush_comp;      /* DS flush completed */
+       u32     ds_xfrdy_exp;       /* DS XFER_RDY expired */
+       u32     ds_seq_cnt_err;     /* DS seq cnt error */
+       u32     ds_seq_len_err;     /* DS seq len error */
+       u32     ds_data_oor;        /* DS data out of order */
+       u32     ds_hit_bls;     /* DS hit BLS */
+       u32     ds_edtov_timer_exp; /* DS edtov expired */
+       u32     ds_cpu_owned;       /* DS cpu owned */
+       u32     ds_hit_class2;      /* DS hit class2 */
+       u32     ds_length_err;      /* DS length error */
+       u32     ds_ro_ooo_err;      /* DS relative offset out-of-order error */
+       u32     ds_rectov_timer_exp;    /* DS rectov expired */
+       u32     ds_unexp_fr_err;    /* DS unexp frame error */
+};
+
+/*
+ * IOC firmware IO stats
+ */
+struct bfa_fw_io_stats_s {
+       struct bfa_fw_ioim_stats_s      ioim_stats;
+       struct bfa_fw_tio_stats_s       tio_stats;
+};
+
 /*
  * IOC port firmware stats
  */
@@ -205,6 +256,7 @@ struct bfa_fw_port_lksm_stats_s {
     u32    nos_tx;             /*  No. of times NOS tx started         */
     u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */
     u32    hwsm_lr_rx;         /*  No. of times LR rx-ed by HWSM      */
+       u32     bbsc_lr;        /* LKSM LR tx for credit recovery       */
 };
 
 struct bfa_fw_port_snsm_stats_s {
@@ -266,8 +318,8 @@ struct bfa_fw_fcoe_stats_s {
  * IOC firmware FCoE port stats
  */
 struct bfa_fw_fcoe_port_stats_s {
-    struct bfa_fw_fcoe_stats_s  fcoe_stats;
-    struct bfa_fw_fip_stats_s   fip_stats;
+       struct bfa_fw_fcoe_stats_s  fcoe_stats;
+       struct bfa_fw_fip_stats_s   fip_stats;
 };
 
 /*
@@ -636,6 +688,7 @@ enum bfa_port_states {
        BFA_PORT_ST_FWMISMATCH          = 12,
        BFA_PORT_ST_PREBOOT_DISABLED    = 13,
        BFA_PORT_ST_TOGGLING_QWAIT      = 14,
+       BFA_PORT_ST_ACQ_ADDR            = 15,
        BFA_PORT_ST_MAX_STATE,
 };
 
@@ -748,6 +801,10 @@ struct bfa_port_cfg_s {
        u8       tx_bbcredit;   /*  transmit buffer credits     */
        u8       ratelimit;     /*  ratelimit enabled or not    */
        u8       trl_def_speed; /*  ratelimit default speed     */
+       u8      bb_scn;         /*  BB_SCN value from FLOGI Exchg */
+       u8      bb_scn_state;   /*  Config state of BB_SCN */
+       u8      faa_state;      /*  FAA enabled/disabled        */
+       u8      rsvd[1];
        u16 path_tov;   /*  device path timeout */
        u16 q_depth;    /*  SCSI Queue depth            */
 };
@@ -783,7 +840,7 @@ struct bfa_port_attr_s {
        enum bfa_port_topology  topology;       /*  current topology */
        bfa_boolean_t           beacon;         /*  current beacon status */
        bfa_boolean_t           link_e2e_beacon; /*  link beacon is on */
-       bfa_boolean_t           plog_enabled;   /*  portlog is enabled */
+       bfa_boolean_t   bbsc_op_status; /* fc credit recovery oper state */
 
        /*
         * Dynamic field - info from FCS
@@ -792,12 +849,10 @@ struct bfa_port_attr_s {
        enum bfa_port_type      port_type;      /*  current topology */
        u32             loopback;       /*  external loopback */
        u32             authfail;       /*  auth fail state */
-       bfa_boolean_t           io_profile;     /*  get it from fcpim mod */
-       u8                      pad[4];         /*  for 64-bit alignement */
 
        /* FCoE specific  */
        u16             fcoe_vlan;
-       u8                      rsvd1[6];
+       u8                      rsvd1[2];
 };
 
 /*
@@ -988,6 +1043,19 @@ struct bfa_itnim_ioprofile_s {
 };
 
 /*
+ *     vHBA port attribute values.
+ */
+struct bfa_vhba_attr_s {
+       wwn_t   nwwn;       /* node wwn */
+       wwn_t   pwwn;       /* port wwn */
+       u32     pid;        /* port ID */
+       bfa_boolean_t       io_profile; /* get it from fcpim mod */
+       bfa_boolean_t       plog_enabled;   /* portlog is enabled */
+       u16     path_tov;
+       u8      rsvd[2];
+};
+
+/*
  * FC physical port statistics.
  */
 struct bfa_port_fc_stats_s {
@@ -1020,6 +1088,9 @@ struct bfa_port_fc_stats_s {
        u64     bad_os_count;   /*  Invalid ordered sets        */
        u64     err_enc_out;    /*  Encoding err nonframe_8b10b */
        u64     err_enc;        /*  Encoding err frame_8b10b    */
+       u64     bbsc_frames_lost; /* Credit Recovery-Frames Lost  */
+       u64     bbsc_credits_lost; /* Credit Recovery-Credits Lost */
+       u64     bbsc_link_resets; /* Credit Recovery-Link Resets   */
 };
 
 /*
@@ -1078,4 +1149,83 @@ union bfa_port_stats_u {
        struct bfa_port_eth_stats_s     eth;
 };
 
+struct bfa_port_cfg_mode_s {
+       u16             max_pf;
+       u16             max_vf;
+       enum bfa_mode_s mode;
+};
+
+#pragma pack(1)
+
+#define BFA_CEE_LLDP_MAX_STRING_LEN    (128)
+#define BFA_CEE_DCBX_MAX_PRIORITY      (8)
+#define BFA_CEE_DCBX_MAX_PGID          (8)
+
+struct bfa_cee_lldp_str_s {
+       u8      sub_type;
+       u8      len;
+       u8      rsvd[2];
+       u8      value[BFA_CEE_LLDP_MAX_STRING_LEN];
+};
+
+struct bfa_cee_lldp_cfg_s {
+       struct bfa_cee_lldp_str_s chassis_id;
+       struct bfa_cee_lldp_str_s port_id;
+       struct bfa_cee_lldp_str_s port_desc;
+       struct bfa_cee_lldp_str_s sys_name;
+       struct bfa_cee_lldp_str_s sys_desc;
+       struct bfa_cee_lldp_str_s mgmt_addr;
+       u16     time_to_live;
+       u16     enabled_system_cap;
+};
+
+/* CEE/DCBX parameters */
+struct bfa_cee_dcbx_cfg_s {
+       u8      pgid[BFA_CEE_DCBX_MAX_PRIORITY];
+       u8      pg_percentage[BFA_CEE_DCBX_MAX_PGID];
+       u8      pfc_primap; /* bitmap of priorties with PFC enabled */
+       u8      fcoe_primap; /* bitmap of priorities used for FcoE traffic */
+       u8      iscsi_primap; /* bitmap of priorities used for iSCSI traffic */
+       u8      dcbx_version; /* operating version:CEE or preCEE */
+       u8      lls_fcoe; /* FCoE Logical Link Status */
+       u8      lls_lan; /* LAN Logical Link Status */
+       u8      rsvd[2];
+};
+
+/* CEE Query */
+struct bfa_cee_attr_s {
+       u8      cee_status;
+       u8      error_reason;
+       struct bfa_cee_lldp_cfg_s lldp_remote;
+       struct bfa_cee_dcbx_cfg_s dcbx_remote;
+       mac_t src_mac;
+       u8      link_speed;
+       u8      nw_priority;
+       u8      filler[2];
+};
+
+/* LLDP/DCBX/CEE Statistics */
+struct bfa_cee_stats_s {
+       u32             lldp_tx_frames;         /* LLDP Tx Frames */
+       u32             lldp_rx_frames;         /* LLDP Rx Frames */
+       u32             lldp_rx_frames_invalid; /* LLDP Rx Frames invalid */
+       u32             lldp_rx_frames_new;     /* LLDP Rx Frames new */
+       u32             lldp_tlvs_unrecognized; /* LLDP Rx unrecog. TLVs */
+       u32             lldp_rx_shutdown_tlvs;  /* LLDP Rx shutdown TLVs */
+       u32             lldp_info_aged_out;     /* LLDP remote info aged */
+       u32             dcbx_phylink_ups;       /* DCBX phy link ups */
+       u32             dcbx_phylink_downs;     /* DCBX phy link downs */
+       u32             dcbx_rx_tlvs;           /* DCBX Rx TLVs */
+       u32             dcbx_rx_tlvs_invalid;   /* DCBX Rx TLVs invalid */
+       u32             dcbx_control_tlv_error; /* DCBX control TLV errors */
+       u32             dcbx_feature_tlv_error; /* DCBX feature TLV errors */
+       u32             dcbx_cee_cfg_new;       /* DCBX new CEE cfg rcvd */
+       u32             cee_status_down;        /* DCB status down */
+       u32             cee_status_up;          /* DCB status up */
+       u32             cee_hw_cfg_changed;     /* DCB hw cfg changed */
+       u32             cee_rx_invalid_cfg;     /* DCB invalid cfg */
+};
+
+#pragma pack()
+
 #endif /* __BFA_DEFS_SVC_H__ */
index bf0067e..8d0b88f 100644 (file)
@@ -1021,7 +1021,7 @@ struct fc_symname_s {
 #define FC_ED_TOV      2
 #define FC_REC_TOV     (FC_ED_TOV + 1)
 #define FC_RA_TOV      10
-#define FC_ELS_TOV     (2 * FC_RA_TOV)
+#define FC_ELS_TOV     ((2 * FC_RA_TOV) + 1)
 #define FC_FCCT_TOV    (3 * FC_RA_TOV)
 
 /*
@@ -1049,15 +1049,6 @@ struct fc_vft_s {
 };
 
 /*
- * FCP
- */
-enum {
-       FCP_RJT         = 0x01000000,   /* SRR reject */
-       FCP_SRR_ACCEPT  = 0x02000000,   /* SRR accept */
-       FCP_SRR         = 0x14000000,   /* Sequence Retransmission Request */
-};
-
-/*
  * FCP_CMND definitions
  */
 #define FCP_CMND_CDB_LEN    16
index b7e2534..17b59b8 100644 (file)
@@ -94,7 +94,6 @@ fcbuild_init(void)
         */
        plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
        plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
-       plogi_tmpl.csp.bbcred = cpu_to_be16(0x0004);
        plogi_tmpl.csp.ciro = 0x1;
        plogi_tmpl.csp.cisc = 0x0;
        plogi_tmpl.csp.altbbcred = 0x0;
@@ -156,6 +155,22 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
         */
 }
 
+static void
+fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+       memset(fchs, 0, sizeof(struct fchs_s));
+
+       fchs->routing = FC_RTG_FC4_DEV_DATA;
+       fchs->cat_info = FC_CAT_SOLICIT_CTRL;
+       fchs->type = FC_TYPE_SERVICES;
+       fchs->f_ctl =
+               bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+                          FCTL_END_SEQ | FCTL_SI_XFER);
+       fchs->d_id = d_id;
+       fchs->s_id = s_id;
+       fchs->ox_id = ox_id;
+}
+
 void
 fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
 {
@@ -207,7 +222,7 @@ fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
 static          u16
 fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
                 __be16 ox_id, wwn_t port_name, wwn_t node_name,
-                u16 pdu_size, u8 els_code)
+                u16 pdu_size, u16 bb_cr, u8 els_code)
 {
        struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
 
@@ -220,6 +235,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
                fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
        plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
+       plogi->csp.bbcred  = cpu_to_be16(bb_cr);
 
        memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
        memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
@@ -268,15 +284,17 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 u16
 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
                   __be16 ox_id, wwn_t port_name, wwn_t node_name,
-                  u16 pdu_size, u16 local_bb_credits)
+                  u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
 {
        u32        d_id = 0;
+       u16        bbscn_rxsz = (bb_scn << 12) | pdu_size;
 
        memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
        fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
        flogi->els_cmd.els_code = FC_ELS_ACC;
-       flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
+       flogi->class3.rxsz = cpu_to_be16(pdu_size);
+       flogi->csp.rxsz  = cpu_to_be16(bbscn_rxsz);     /* bb_scn/rxsz */
        flogi->port_name = port_name;
        flogi->node_name = node_name;
 
@@ -306,19 +324,19 @@ fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 u16
 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
               u16 ox_id, wwn_t port_name, wwn_t node_name,
-              u16 pdu_size)
+              u16 pdu_size, u16 bb_cr)
 {
        return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
-                               node_name, pdu_size, FC_ELS_PLOGI);
+                               node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
 }
 
 u16
 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
                   u16 ox_id, wwn_t port_name, wwn_t node_name,
-                  u16 pdu_size)
+                  u16 pdu_size, u16 bb_cr)
 {
        return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
-                               node_name, pdu_size, FC_ELS_ACC);
+                               node_name, pdu_size, bb_cr, FC_ELS_ACC);
 }
 
 enum fc_parse_status
@@ -1096,6 +1114,21 @@ fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
 }
 
 u16
+fc_gs_rjt_build(struct fchs_s *fchs,  struct ct_hdr_s *cthdr,
+               u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
+               u8 reason_code_expl)
+{
+       fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id);
+
+       cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT);
+       cthdr->rev_id = CT_GS3_REVISION;
+
+       cthdr->reason_code = reason_code;
+       cthdr->exp_code    = reason_code_expl;
+       return sizeof(struct ct_hdr_s);
+}
+
+u16
 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
                u8 set_br_reg, u32 s_id, u16 ox_id)
 {
index ece51ec..42cd9d4 100644 (file)
@@ -66,6 +66,9 @@ fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
        case RPSC_OP_SPEED_8G:
                return BFA_PORT_SPEED_8GBPS;
 
+       case RPSC_OP_SPEED_16G:
+               return BFA_PORT_SPEED_16GBPS;
+
        case RPSC_OP_SPEED_10G:
                return BFA_PORT_SPEED_10GBPS;
 
@@ -94,6 +97,9 @@ fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
        case BFA_PORT_SPEED_8GBPS:
                return RPSC_OP_SPEED_8G;
 
+       case BFA_PORT_SPEED_16GBPS:
+               return RPSC_OP_SPEED_16G;
+
        case BFA_PORT_SPEED_10GBPS:
                return RPSC_OP_SPEED_10G;
 
@@ -141,11 +147,11 @@ 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);
+                                  u16 local_bb_credits, u8 bb_scn);
 
 u16        fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
                               u32 s_id, u16 ox_id, wwn_t port_name,
-                              wwn_t node_name, u16 pdu_size);
+                              wwn_t node_name, u16 pdu_size, u16 bb_cr);
 
 enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
 
@@ -177,13 +183,17 @@ u16        fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
 u16        fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
                               u16 ox_id, u32 port_id);
 
+u16    fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       u8 reason_code, u8 reason_code_expl);
+
 u16        fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
                        u8 set_br_reg, u32 s_id, u16 ox_id);
 
 u16        fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
                                   u32 s_id, u16 ox_id,
                                   wwn_t port_name, wwn_t node_name,
-                                  u16 pdu_size);
+                                  u16 pdu_size, u16 bb_cr);
 
 u16        fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
                        u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
index c0353cd..a4e7951 100644 (file)
@@ -19,7 +19,6 @@
 #include "bfa_modules.h"
 
 BFA_TRC_FILE(HAL, FCPIM);
-BFA_MODULE(fcpim);
 
 /*
  *  BFA ITNIM Related definitions
@@ -287,24 +286,16 @@ static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
  * Compute and return memory needed by FCP(im) module.
  */
 static void
-bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-               u32 *dm_len)
+bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
 {
-       bfa_itnim_meminfo(cfg, km_len, dm_len);
+       bfa_itnim_meminfo(cfg, km_len);
 
        /*
         * IO memory
         */
-       if (cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
-               cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
-       else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
-               cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
-
        *km_len += cfg->fwcfg.num_ioim_reqs *
          (sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s));
 
-       *dm_len += cfg->fwcfg.num_ioim_reqs * BFI_IOIM_SNSLEN;
-
        /*
         * task management command memory
         */
@@ -315,52 +306,41 @@ bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
 
 
 static void
-bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-               struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+bfa_fcpim_attach(struct bfa_fcp_mod_s *fcp, void *bfad,
+               struct bfa_iocfc_cfg_s *cfg, struct bfa_pcidev_s *pcidev)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = &fcp->fcpim;
+       struct bfa_s *bfa = fcp->bfa;
 
        bfa_trc(bfa, cfg->drvcfg.path_tov);
        bfa_trc(bfa, cfg->fwcfg.num_rports);
        bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
        bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
 
+       fcpim->fcp              = fcp;
        fcpim->bfa              = bfa;
        fcpim->num_itnims       = cfg->fwcfg.num_rports;
-       fcpim->num_ioim_reqs  = cfg->fwcfg.num_ioim_reqs;
        fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
        fcpim->path_tov         = cfg->drvcfg.path_tov;
        fcpim->delay_comp       = cfg->drvcfg.delay_comp;
        fcpim->profile_comp = NULL;
        fcpim->profile_start = NULL;
 
-       bfa_itnim_attach(fcpim, meminfo);
-       bfa_tskim_attach(fcpim, meminfo);
-       bfa_ioim_attach(fcpim, meminfo);
-}
-
-static void
-bfa_fcpim_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcpim_start(struct bfa_s *bfa)
-{
+       bfa_itnim_attach(fcpim);
+       bfa_tskim_attach(fcpim);
+       bfa_ioim_attach(fcpim);
 }
 
 static void
-bfa_fcpim_stop(struct bfa_s *bfa)
+bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *fcp)
 {
-}
-
-static void
-bfa_fcpim_iocdisable(struct bfa_s *bfa)
-{
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = &fcp->fcpim;
        struct bfa_itnim_s *itnim;
        struct list_head *qe, *qen;
 
+       /* Enqueue unused ioim resources to free_q */
+       list_splice_tail_init(&fcpim->tskim_unused_q, &fcpim->tskim_free_q);
+
        list_for_each_safe(qe, qen, &fcpim->itnim_q) {
                itnim = (struct bfa_itnim_s *) qe;
                bfa_itnim_iocdisable(itnim);
@@ -370,7 +350,7 @@ bfa_fcpim_iocdisable(struct bfa_s *bfa)
 void
 bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 
        fcpim->path_tov = path_tov * 1000;
        if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX)
@@ -380,15 +360,87 @@ bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
 u16
 bfa_fcpim_path_tov_get(struct bfa_s *bfa)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 
        return fcpim->path_tov / 1000;
 }
 
+#define bfa_fcpim_add_iostats(__l, __r, __stats)       \
+       (__l->__stats += __r->__stats)
+
+void
+bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
+               struct bfa_itnim_iostats_s *rstats)
+{
+       bfa_fcpim_add_iostats(lstats, rstats, total_ios);
+       bfa_fcpim_add_iostats(lstats, rstats, qresumes);
+       bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
+       bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
+       bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
+       bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
+       bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
+       bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
+       bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
+       bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
+       bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
+       bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
+       bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
+       bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
+       bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
+       bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
+       bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
+       bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
+       bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
+       bfa_fcpim_add_iostats(lstats, rstats, onlines);
+       bfa_fcpim_add_iostats(lstats, rstats, offlines);
+       bfa_fcpim_add_iostats(lstats, rstats, creates);
+       bfa_fcpim_add_iostats(lstats, rstats, deletes);
+       bfa_fcpim_add_iostats(lstats, rstats, create_comps);
+       bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
+       bfa_fcpim_add_iostats(lstats, rstats, sler_events);
+       bfa_fcpim_add_iostats(lstats, rstats, fw_create);
+       bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
+       bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
+       bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_success);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
+       bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
+       bfa_fcpim_add_iostats(lstats, rstats, io_comps);
+       bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
+       bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
+       bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
+       bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
+}
+
+bfa_status_t
+bfa_fcpim_port_iostats(struct bfa_s *bfa,
+               struct bfa_itnim_iostats_s *stats, u8 lp_tag)
+{
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+       struct list_head *qe, *qen;
+       struct bfa_itnim_s *itnim;
+
+       /* accumulate IO stats from itnim */
+       memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
+       list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+               itnim = (struct bfa_itnim_s *) qe;
+               if (itnim->rport->rport_info.lp_tag != lp_tag)
+                       continue;
+               bfa_fcpim_add_stats(stats, &(itnim->stats));
+       }
+       return BFA_STATUS_OK;
+}
+
 u16
 bfa_fcpim_qdepth_get(struct bfa_s *bfa)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 
        return fcpim->q_depth;
 }
@@ -990,8 +1042,7 @@ bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
 }
 
 void
-bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-               u32 *dm_len)
+bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
 {
        /*
         * ITN memory
@@ -1000,15 +1051,16 @@ bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
 }
 
 void
-bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_itnim_attach(struct bfa_fcpim_s *fcpim)
 {
        struct bfa_s    *bfa = fcpim->bfa;
+       struct bfa_fcp_mod_s    *fcp = fcpim->fcp;
        struct bfa_itnim_s *itnim;
        int     i, j;
 
        INIT_LIST_HEAD(&fcpim->itnim_q);
 
-       itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
+       itnim = (struct bfa_itnim_s *) bfa_mem_kva_curp(fcp);
        fcpim->itnim_arr = itnim;
 
        for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
@@ -1030,7 +1082,7 @@ bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
                bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
        }
 
-       bfa_meminfo_kva(minfo) = (u8 *) itnim;
+       bfa_mem_kva_curp(fcp) = (u8 *) itnim;
 }
 
 void
@@ -1043,7 +1095,7 @@ bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
 static bfa_boolean_t
 bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
 {
-       struct bfi_itnim_create_req_s *m;
+       struct bfi_itn_create_req_s *m;
 
        itnim->msg_no++;
 
@@ -1056,8 +1108,8 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
                return BFA_FALSE;
        }
 
-       bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
-                       bfa_lpuid(itnim->bfa));
+       bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_CREATE_REQ,
+                       bfa_fn_lpu(itnim->bfa));
        m->fw_handle = itnim->rport->fw_handle;
        m->class = FC_CLASS_3;
        m->seq_rec = itnim->seq_rec;
@@ -1067,14 +1119,14 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
        /*
         * queue I/O message to firmware
         */
-       bfa_reqq_produce(itnim->bfa, itnim->reqq);
+       bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
        return BFA_TRUE;
 }
 
 static bfa_boolean_t
 bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
 {
-       struct bfi_itnim_delete_req_s *m;
+       struct bfi_itn_delete_req_s *m;
 
        /*
         * check for room in queue to send request now
@@ -1085,15 +1137,15 @@ bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
                return BFA_FALSE;
        }
 
-       bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
-                       bfa_lpuid(itnim->bfa));
+       bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_DELETE_REQ,
+                       bfa_fn_lpu(itnim->bfa));
        m->fw_handle = itnim->rport->fw_handle;
        bfa_stats(itnim, fw_delete);
 
        /*
         * queue I/O message to firmware
         */
-       bfa_reqq_produce(itnim->bfa, itnim->reqq);
+       bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
        return BFA_TRUE;
 }
 
@@ -1224,7 +1276,7 @@ bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
 static void
 bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);
        fcpim->del_itn_stats.del_itn_iocomp_aborted +=
                itnim->stats.iocomp_aborted;
        fcpim->del_itn_stats.del_itn_iocomp_timedout +=
@@ -1250,8 +1302,8 @@ bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
 void
 bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-       union bfi_itnim_i2h_msg_u msg;
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+       union bfi_itn_i2h_msg_u msg;
        struct bfa_itnim_s *itnim;
 
        bfa_trc(bfa, m->mhdr.msg_id);
@@ -1259,7 +1311,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
        msg.msg = m;
 
        switch (m->mhdr.msg_id) {
-       case BFI_ITNIM_I2H_CREATE_RSP:
+       case BFI_ITN_I2H_CREATE_RSP:
                itnim = BFA_ITNIM_FROM_TAG(fcpim,
                                                msg.create_rsp->bfa_handle);
                WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
@@ -1267,7 +1319,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
                break;
 
-       case BFI_ITNIM_I2H_DELETE_RSP:
+       case BFI_ITN_I2H_DELETE_RSP:
                itnim = BFA_ITNIM_FROM_TAG(fcpim,
                                                msg.delete_rsp->bfa_handle);
                WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
@@ -1275,7 +1327,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
                break;
 
-       case BFI_ITNIM_I2H_SLER_EVENT:
+       case BFI_ITN_I2H_SLER_EVENT:
                itnim = BFA_ITNIM_FROM_TAG(fcpim,
                                                msg.sler_event->bfa_handle);
                bfa_stats(itnim, sler_events);
@@ -1295,9 +1347,11 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 struct bfa_itnim_s *
 bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
        struct bfa_itnim_s *itnim;
 
+       bfa_itn_create(bfa, rport, bfa_itnim_isr);
+
        itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
        WARN_ON(itnim->rport != rport);
 
@@ -1991,7 +2045,8 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
                if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&
                                        m->sns_len) {
                        sns_len = m->sns_len;
-                       snsinfo = ioim->iosp->snsinfo;
+                       snsinfo = BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
+                                               ioim->iotag);
                }
 
                /*
@@ -2189,12 +2244,12 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
         */
        switch (m->cmnd.iodir) {
        case FCP_IODIR_READ:
-               bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_fn_lpu(ioim->bfa));
                bfa_stats(itnim, input_reqs);
                ioim->itnim->stats.rd_throughput += fcp_dl;
                break;
        case FCP_IODIR_WRITE:
-               bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_fn_lpu(ioim->bfa));
                bfa_stats(itnim, output_reqs);
                ioim->itnim->stats.wr_throughput += fcp_dl;
                break;
@@ -2202,16 +2257,16 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
                bfa_stats(itnim, input_reqs);
                bfa_stats(itnim, output_reqs);
        default:
-               bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
        }
        if (itnim->seq_rec ||
            (scsi_bufflen(cmnd) & (sizeof(u32) - 1)))
-               bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
 
        /*
         * queue I/O message to firmware
         */
-       bfa_reqq_produce(ioim->bfa, ioim->reqq);
+       bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
        return BFA_TRUE;
 }
 
@@ -2269,14 +2324,14 @@ bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
        else
                msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
 
-       bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
+       bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_fn_lpu(ioim->bfa));
        m->io_tag    = cpu_to_be16(ioim->iotag);
        m->abort_tag = ++ioim->abort_tag;
 
        /*
         * queue I/O message to firmware
         */
-       bfa_reqq_produce(ioim->bfa, ioim->reqq);
+       bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
        return BFA_TRUE;
 }
 
@@ -2360,46 +2415,32 @@ bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
  * Memory allocation and initialization.
  */
 void
-bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
 {
        struct bfa_ioim_s               *ioim;
+       struct bfa_fcp_mod_s    *fcp = fcpim->fcp;
        struct bfa_ioim_sp_s    *iosp;
        u16             i;
-       u8                      *snsinfo;
-       u32             snsbufsz;
 
        /*
         * claim memory first
         */
-       ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
+       ioim = (struct bfa_ioim_s *) bfa_mem_kva_curp(fcp);
        fcpim->ioim_arr = ioim;
-       bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
+       bfa_mem_kva_curp(fcp) = (u8 *) (ioim + fcpim->fcp->num_ioim_reqs);
 
-       iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
+       iosp = (struct bfa_ioim_sp_s *) bfa_mem_kva_curp(fcp);
        fcpim->ioim_sp_arr = iosp;
-       bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
-
-       /*
-        * Claim DMA memory for per IO sense data.
-        */
-       snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
-       fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
-       bfa_meminfo_dma_phys(minfo) += snsbufsz;
-
-       fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
-       bfa_meminfo_dma_virt(minfo) += snsbufsz;
-       snsinfo = fcpim->snsbase.kva;
-       bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
+       bfa_mem_kva_curp(fcp) = (u8 *) (iosp + fcpim->fcp->num_ioim_reqs);
 
        /*
         * Initialize ioim free queues
         */
-       INIT_LIST_HEAD(&fcpim->ioim_free_q);
        INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
        INIT_LIST_HEAD(&fcpim->ioim_comp_q);
 
-       for (i = 0; i < fcpim->num_ioim_reqs;
-            i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
+       for (i = 0; i < fcpim->fcp->num_ioim_reqs;
+            i++, ioim++, iosp++) {
                /*
                 * initialize IOIM
                 */
@@ -2408,22 +2449,19 @@ bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
                ioim->bfa     = fcpim->bfa;
                ioim->fcpim   = fcpim;
                ioim->iosp    = iosp;
-               iosp->snsinfo = snsinfo;
                INIT_LIST_HEAD(&ioim->sgpg_q);
                bfa_reqq_winit(&ioim->iosp->reqq_wait,
                                   bfa_ioim_qresume, ioim);
                bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
                                   bfa_ioim_sgpg_alloced, ioim);
                bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-
-               list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
        }
 }
 
 void
 bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
        struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
        struct bfa_ioim_s *ioim;
        u16     iotag;
@@ -2507,7 +2545,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 void
 bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
        struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
        struct bfa_ioim_s *ioim;
        u16     iotag;
@@ -2573,18 +2611,21 @@ struct bfa_ioim_s *
 bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
                struct bfa_itnim_s *itnim, u16 nsges)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
        struct bfa_ioim_s *ioim;
+       struct bfa_iotag_s *iotag = NULL;
 
        /*
         * alocate IOIM resource
         */
-       bfa_q_deq(&fcpim->ioim_free_q, &ioim);
-       if (!ioim) {
+       bfa_q_deq(&fcpim->fcp->iotag_ioim_free_q, &iotag);
+       if (!iotag) {
                bfa_stats(itnim, no_iotags);
                return NULL;
        }
 
+       ioim = BFA_IOIM_FROM_TAG(fcpim, iotag->tag);
+
        ioim->dio = dio;
        ioim->itnim = itnim;
        ioim->nsges = nsges;
@@ -2601,7 +2642,8 @@ bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
 void
 bfa_ioim_free(struct bfa_ioim_s *ioim)
 {
-       struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
+       struct bfa_fcpim_s *fcpim = ioim->fcpim;
+       struct bfa_iotag_s *iotag;
 
        if (ioim->nsgpgs > 0)
                bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
@@ -2610,8 +2652,17 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
        fcpim->ios_active--;
 
        ioim->iotag &= BFA_IOIM_IOTAG_MASK;
+
+       WARN_ON(!(ioim->iotag <
+               (fcpim->fcp->num_ioim_reqs + fcpim->fcp->num_fwtio_reqs)));
+       iotag = BFA_IOTAG_FROM_TAG(fcpim->fcp, ioim->iotag);
+
+       if (ioim->iotag < fcpim->fcp->num_ioim_reqs)
+               list_add_tail(&iotag->qe, &fcpim->fcp->iotag_ioim_free_q);
+       else
+               list_add_tail(&iotag->qe, &fcpim->fcp->iotag_tio_free_q);
+
        list_del(&ioim->qe);
-       list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
 }
 
 void
@@ -3021,7 +3072,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)
         * build i/o request message next
         */
        bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
-                       bfa_lpuid(tskim->bfa));
+                       bfa_fn_lpu(tskim->bfa));
 
        m->tsk_tag = cpu_to_be16(tskim->tsk_tag);
        m->itn_fhdl = tskim->itnim->rport->fw_handle;
@@ -3032,7 +3083,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)
        /*
         * queue I/O message to firmware
         */
-       bfa_reqq_produce(tskim->bfa, itnim->reqq);
+       bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
        return BFA_TRUE;
 }
 
@@ -3056,14 +3107,14 @@ bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
         * build i/o request message next
         */
        bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
-                       bfa_lpuid(tskim->bfa));
+                       bfa_fn_lpu(tskim->bfa));
 
        m->tsk_tag  = cpu_to_be16(tskim->tsk_tag);
 
        /*
         * queue I/O message to firmware
         */
-       bfa_reqq_produce(tskim->bfa, itnim->reqq);
+       bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
        return BFA_TRUE;
 }
 
@@ -3129,14 +3180,16 @@ bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
  * Memory allocation and initialization.
  */
 void
-bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_tskim_attach(struct bfa_fcpim_s *fcpim)
 {
        struct bfa_tskim_s *tskim;
+       struct bfa_fcp_mod_s    *fcp = fcpim->fcp;
        u16     i;
 
        INIT_LIST_HEAD(&fcpim->tskim_free_q);
+       INIT_LIST_HEAD(&fcpim->tskim_unused_q);
 
-       tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
+       tskim = (struct bfa_tskim_s *) bfa_mem_kva_curp(fcp);
        fcpim->tskim_arr = tskim;
 
        for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
@@ -3155,13 +3208,13 @@ bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
                list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
        }
 
-       bfa_meminfo_kva(minfo) = (u8 *) tskim;
+       bfa_mem_kva_curp(fcp) = (u8 *) tskim;
 }
 
 void
 bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
        struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
        struct bfa_tskim_s *tskim;
        u16     tsk_tag = be16_to_cpu(rsp->tsk_tag);
@@ -3188,7 +3241,7 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 struct bfa_tskim_s *
 bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
 {
-       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
        struct bfa_tskim_s *tskim;
 
        bfa_q_deq(&fcpim->tskim_free_q, &tskim);
@@ -3233,3 +3286,214 @@ bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim,
        list_add_tail(&tskim->qe, &itnim->tsk_q);
        bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
 }
+
+void
+bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw)
+{
+       struct bfa_fcpim_s      *fcpim = BFA_FCPIM(bfa);
+       struct list_head        *qe;
+       int     i;
+
+       for (i = 0; i < (fcpim->num_tskim_reqs - num_tskim_fw); i++) {
+               bfa_q_deq_tail(&fcpim->tskim_free_q, &qe);
+               list_add_tail(qe, &fcpim->tskim_unused_q);
+       }
+}
+
+/* BFA FCP module - parent module for fcpim */
+
+BFA_MODULE(fcp);
+
+static void
+bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+               struct bfa_s *bfa)
+{
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+       struct bfa_mem_kva_s *fcp_kva = BFA_MEM_FCP_KVA(bfa);
+       struct bfa_mem_dma_s *seg_ptr;
+       u16     nsegs, idx, per_seg_ios, num_io_req;
+       u32     km_len = 0;
+
+       /*
+        * ZERO for num_ioim_reqs and num_fwtio_reqs is allowed config value.
+        * So if the values are non zero, adjust them appropriately.
+        */
+       if (cfg->fwcfg.num_ioim_reqs &&
+           cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
+               cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
+       else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
+               cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
+
+       if (cfg->fwcfg.num_fwtio_reqs > BFA_FWTIO_MAX)
+               cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
+
+       num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+       if (num_io_req > BFA_IO_MAX) {
+               if (cfg->fwcfg.num_ioim_reqs && cfg->fwcfg.num_fwtio_reqs) {
+                       cfg->fwcfg.num_ioim_reqs = BFA_IO_MAX/2;
+                       cfg->fwcfg.num_fwtio_reqs = BFA_IO_MAX/2;
+               } else if (cfg->fwcfg.num_fwtio_reqs)
+                       cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
+               else
+                       cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
+       }
+
+       bfa_fcpim_meminfo(cfg, &km_len);
+
+       num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+       km_len += num_io_req * sizeof(struct bfa_iotag_s);
+       km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itn_s);
+
+       /* dma memory */
+       nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
+       per_seg_ios = BFI_MEM_NREQS_SEG(BFI_IOIM_SNSLEN);
+
+       bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
+               if (num_io_req >= per_seg_ios) {
+                       num_io_req -= per_seg_ios;
+                       bfa_mem_dma_setup(minfo, seg_ptr,
+                               per_seg_ios * BFI_IOIM_SNSLEN);
+               } else
+                       bfa_mem_dma_setup(minfo, seg_ptr,
+                               num_io_req * BFI_IOIM_SNSLEN);
+       }
+
+       /* kva memory */
+       bfa_mem_kva_setup(minfo, fcp_kva, km_len);
+}
+
+static void
+bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+               struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+       struct bfa_mem_dma_s *seg_ptr;
+       u16     idx, nsegs, num_io_req;
+
+       fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
+       fcp->num_fwtio_reqs  = cfg->fwcfg.num_fwtio_reqs;
+       fcp->num_itns   = cfg->fwcfg.num_rports;
+       fcp->bfa = bfa;
+
+       /*
+        * Setup the pool of snsbase addr's, that is passed to fw as
+        * part of bfi_iocfc_cfg_s.
+        */
+       num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+       nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
+
+       bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
+
+               if (!bfa_mem_dma_virt(seg_ptr))
+                       break;
+
+               fcp->snsbase[idx].pa = bfa_mem_dma_phys(seg_ptr);
+               fcp->snsbase[idx].kva = bfa_mem_dma_virt(seg_ptr);
+               bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
+       }
+
+       bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
+
+       bfa_iotag_attach(fcp);
+
+       fcp->itn_arr = (struct bfa_itn_s *) bfa_mem_kva_curp(fcp);
+       bfa_mem_kva_curp(fcp) = (u8 *)fcp->itn_arr +
+                       (fcp->num_itns * sizeof(struct bfa_itn_s));
+       memset(fcp->itn_arr, 0,
+                       (fcp->num_itns * sizeof(struct bfa_itn_s)));
+}
+
+static void
+bfa_fcp_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_iocdisable(struct bfa_s *bfa)
+{
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+
+       /* Enqueue unused ioim resources to free_q */
+       list_splice_tail_init(&fcp->iotag_unused_q, &fcp->iotag_ioim_free_q);
+
+       bfa_fcpim_iocdisable(fcp);
+}
+
+void
+bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw)
+{
+       struct bfa_fcp_mod_s    *mod = BFA_FCP_MOD(bfa);
+       struct list_head        *qe;
+       int     i;
+
+       for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
+               bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
+               list_add_tail(qe, &mod->iotag_unused_q);
+       }
+}
+
+void
+bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
+               void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m))
+{
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+       struct bfa_itn_s *itn;
+
+       itn =  BFA_ITN_FROM_TAG(fcp, rport->rport_tag);
+       itn->isr = isr;
+}
+
+/*
+ * Itn interrupt processing.
+ */
+void
+bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+       union bfi_itn_i2h_msg_u msg;
+       struct bfa_itn_s *itn;
+
+       msg.msg = m;
+       itn =  BFA_ITN_FROM_TAG(fcp, msg.create_rsp->bfa_handle);
+
+       if (itn->isr)
+               itn->isr(bfa, m);
+       else
+               WARN_ON(1);
+}
+
+void
+bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
+{
+       struct bfa_iotag_s *iotag;
+       u16     num_io_req, i;
+
+       iotag = (struct bfa_iotag_s *) bfa_mem_kva_curp(fcp);
+       fcp->iotag_arr = iotag;
+
+       INIT_LIST_HEAD(&fcp->iotag_ioim_free_q);
+       INIT_LIST_HEAD(&fcp->iotag_tio_free_q);
+       INIT_LIST_HEAD(&fcp->iotag_unused_q);
+
+       num_io_req = fcp->num_ioim_reqs + fcp->num_fwtio_reqs;
+       for (i = 0; i < num_io_req; i++, iotag++) {
+               memset(iotag, 0, sizeof(struct bfa_iotag_s));
+               iotag->tag = i;
+               if (i < fcp->num_ioim_reqs)
+                       list_add_tail(&iotag->qe, &fcp->iotag_ioim_free_q);
+               else
+                       list_add_tail(&iotag->qe, &fcp->iotag_tio_free_q);
+       }
+
+       bfa_mem_kva_curp(fcp) = (u8 *) iotag;
+}
index 1e38dad..57b695a 100644 (file)
 #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);
+
+#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, BFI_IOIM_SNSLEN)
 
 #define BFA_ITNIM_MIN   32
 #define BFA_ITNIM_MAX   1024
@@ -75,25 +103,24 @@ struct bfad_tskim_s;
 
 typedef void    (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
 
-struct bfa_fcpim_mod_s {
+struct bfa_fcpim_s {
        struct bfa_s            *bfa;
+       struct bfa_fcp_mod_s    *fcp;
        struct bfa_itnim_s      *itnim_arr;
        struct bfa_ioim_s       *ioim_arr;
        struct bfa_ioim_sp_s    *ioim_sp_arr;
        struct bfa_tskim_s      *tskim_arr;
-       struct bfa_dma_s        snsbase;
        int                     num_itnims;
-       int                     num_ioim_reqs;
        int                     num_tskim_reqs;
        u32                     path_tov;
        u16                     q_depth;
        u8                      reqq;           /*  Request queue to be used */
        u8                      rsvd;
        struct list_head        itnim_q;        /*  queue of active itnim */
-       struct list_head        ioim_free_q;    /*  free IO resources   */
        struct list_head        ioim_resfree_q; /*  IOs waiting for f/w */
        struct list_head        ioim_comp_q;    /*  IO global comp Q    */
        struct list_head        tskim_free_q;
+       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;
@@ -104,6 +131,25 @@ struct bfa_fcpim_mod_s {
        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                     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;
+};
+
 /*
  * BFA IO (initiator mode)
  */
@@ -111,7 +157,7 @@ struct bfa_ioim_s {
        struct list_head        qe;             /*  queue elememt       */
        bfa_sm_t                sm;             /*  BFA ioim state machine */
        struct bfa_s            *bfa;           /*  BFA module  */
-       struct bfa_fcpim_mod_s  *fcpim;         /*  parent fcpim module */
+       struct bfa_fcpim_s      *fcpim;         /*  parent fcpim module */
        struct bfa_itnim_s      *itnim;         /*  i-t-n nexus for this IO  */
        struct bfad_ioim_s      *dio;           /*  driver IO handle    */
        u16                     iotag;          /*  FWI IO tag  */
@@ -129,7 +175,6 @@ struct bfa_ioim_s {
 
 struct bfa_ioim_sp_s {
        struct bfi_msg_s        comp_rspmsg;    /*  IO comp f/w response */
-       u8                      *snsinfo;       /*  sense info for this IO   */
        struct bfa_sgpg_wqe_s   sgpg_wqe;       /*  waitq elem for sgpg */
        struct bfa_reqq_wait_s  reqq_wait;      /*  to wait for room in reqq */
        bfa_boolean_t           abort_explicit; /*  aborted by OS       */
@@ -143,7 +188,7 @@ struct bfa_tskim_s {
        struct list_head        qe;
        bfa_sm_t                sm;
        struct bfa_s            *bfa;   /*  BFA module  */
-       struct bfa_fcpim_mod_s  *fcpim; /*  parent fcpim module */
+       struct bfa_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  */
@@ -182,13 +227,13 @@ struct bfa_itnim_s {
        struct bfa_wc_s wc;             /*  waiting counter     */
        struct bfa_timer_s timer;       /*  pending IO TOV       */
        struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
-       struct bfa_fcpim_mod_s *fcpim;  /*  fcpim module        */
+       struct bfa_fcpim_s *fcpim;      /*  fcpim module        */
        struct bfa_itnim_iostats_s      stats;
        struct bfa_itnim_ioprofile_s  ioprofile;
 };
 
 #define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
-#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_FCPIM(_hal)        (&(_hal)->modules.fcp_mod.fcpim)
 #define BFA_IOIM_TAG_2_ID(_iotag)      ((_iotag) & BFA_IOIM_IOTAG_MASK)
 #define BFA_IOIM_FROM_TAG(_fcpim, _iotag)      \
        (&fcpim->ioim_arr[(_iotag & BFA_IOIM_IOTAG_MASK)])
@@ -196,9 +241,9 @@ struct bfa_itnim_s {
        (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
 
 #define bfa_io_profile_start_time(_bfa)        \
-       (_bfa->modules.fcpim_mod.io_profile_start_time)
+       ((_bfa)->modules.fcp_mod.fcpim.io_profile_start_time)
 #define bfa_fcpim_get_io_profile(_bfa) \
-       (_bfa->modules.fcpim_mod.io_profile)
+       ((_bfa)->modules.fcp_mod.fcpim.io_profile)
 #define bfa_ioim_update_iotag(__ioim) do {                             \
        uint16_t k = (__ioim)->iotag >> BFA_IOIM_RETRY_TAG_OFFSET;      \
        k++; (__ioim)->iotag &= BFA_IOIM_IOTAG_MASK;                    \
@@ -217,8 +262,7 @@ bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
 /*
  * function prototypes
  */
-void   bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
-                                       struct bfa_meminfo_s *minfo);
+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);
@@ -228,18 +272,15 @@ void      bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
 void   bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
 void   bfa_ioim_tov(struct bfa_ioim_s *ioim);
 
-void   bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
-                                       struct bfa_meminfo_s *minfo);
+void   bfa_tskim_attach(struct bfa_fcpim_s *fcpim);
 void   bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 void   bfa_tskim_iodone(struct bfa_tskim_s *tskim);
 void   bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
 void   bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
+void   bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw);
 
-void   bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-                                       u32 *dm_len);
-void   bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
-                                       struct bfa_meminfo_s *minfo);
-void   bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
+void   bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len);
+void   bfa_itnim_attach(struct bfa_fcpim_s *fcpim);
 void   bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
 void   bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 void   bfa_itnim_iodone(struct bfa_itnim_s *itnim);
@@ -252,13 +293,17 @@ bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
 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);
 
 #define bfa_fcpim_ioredirect_enabled(__bfa)                            \
-       (((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
+       (((struct bfa_fcpim_s *)(BFA_FCPIM(__bfa)))->ioredirect)
 
 #define bfa_fcpim_get_next_reqq(__bfa, __qid)                          \
 {                                                                      \
-       struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa);      \
+       struct bfa_fcpim_s *__fcpim = BFA_FCPIM(__bfa);      \
        __fcpim->reqq++;                                                \
        __fcpim->reqq &= (BFI_IOC_MAX_CQS - 1);      \
        *(__qid) = __fcpim->reqq;                                       \
index 9b43ca4..a9b22bc 100644 (file)
@@ -92,25 +92,49 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
 void
 bfa_fcs_init(struct bfa_fcs_s *fcs)
 {
-       int             i, npbc_vports;
+       int     i;
        struct bfa_fcs_mod_s  *mod;
-       struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
 
        for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
                mod = &fcs_modules[i];
                if (mod->modinit)
                        mod->modinit(fcs);
        }
+}
+
+/*
+ * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
+ * with values learned during bfa_init firmware GETATTR REQ.
+ */
+void
+bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)
+{
+       struct bfa_fcs_fabric_s *fabric = &fcs->fabric;
+       struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+       struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc;
+
+       port_cfg->nwwn = ioc->attr->nwwn;
+       port_cfg->pwwn = ioc->attr->pwwn;
+}
+
+/*
+ * fcs pbc vport initialization
+ */
+void
+bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs)
+{
+       int i, npbc_vports;
+       struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
+
        /* Initialize pbc vports */
        if (!fcs->min_cfg) {
                npbc_vports =
-                   bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
+                       bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
                for (i = 0; i < npbc_vports; i++)
                        bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
        }
 }
 
-
 /*
  *     brief
  *             FCS driver details initialization.
@@ -168,11 +192,14 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)
 #define BFA_FCS_FABRIC_CLEANUP_DELAY   (10000) /* Milliseconds */
 
 #define bfa_fcs_fabric_set_opertype(__fabric) do {                     \
-               if (bfa_fcport_get_topology((__fabric)->fcs->bfa)       \
-                   == BFA_PORT_TOPOLOGY_P2P)                           \
+       if (bfa_fcport_get_topology((__fabric)->fcs->bfa)               \
+                               == BFA_PORT_TOPOLOGY_P2P) {             \
+               if (fabric->fab_type == BFA_FCS_FABRIC_SWITCHED)        \
                        (__fabric)->oper_type = BFA_PORT_TYPE_NPORT;    \
                else                                                    \
-                       (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;   \
+                       (__fabric)->oper_type = BFA_PORT_TYPE_P2P;      \
+       } else                                                          \
+               (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;           \
 } while (0)
 
 /*
@@ -196,6 +223,9 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
                                         u32 rsp_len,
                                         u32 resid_len,
                                         struct fchs_s *rspfchs);
+static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
+static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
+                               struct bfa_fcs_fabric_s *fabric);
 
 static void    bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
                                         enum bfa_fcs_fabric_event event);
@@ -269,8 +299,8 @@ bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
                break;
 
        case BFA_FCS_FABRIC_SM_DELETE:
-               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-               bfa_wc_down(&fabric->fcs->wc);
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_fcs_fabric_delete(fabric);
                break;
 
        default:
@@ -322,7 +352,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
        case BFA_FCS_FABRIC_SM_CONT_OP:
 
                bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
-                                          fabric->bb_credit);
+                                          fabric->bb_credit,
+                                          bfa_fcs_fabric_oper_bbscn(fabric));
                fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
 
                if (fabric->auth_reqd && fabric->is_auth) {
@@ -350,7 +381,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
        case BFA_FCS_FABRIC_SM_NO_FABRIC:
                fabric->fab_type = BFA_FCS_FABRIC_N2N;
                bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
-                                          fabric->bb_credit);
+                                          fabric->bb_credit,
+                                          bfa_fcs_fabric_oper_bbscn(fabric));
                bfa_fcs_fabric_notify_online(fabric);
                bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
                break;
@@ -518,7 +550,11 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
        case BFA_FCS_FABRIC_SM_NO_FABRIC:
                bfa_trc(fabric->fcs, fabric->bb_credit);
                bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
-                                          fabric->bb_credit);
+                                          fabric->bb_credit,
+                                          bfa_fcs_fabric_oper_bbscn(fabric));
+               break;
+
+       case BFA_FCS_FABRIC_SM_RETRY_OP:
                break;
 
        default:
@@ -764,6 +800,10 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
 
        case BFA_STATUS_FABRIC_RJT:
                fabric->stats.flogi_rejects++;
+               if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
+                   fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
+                       fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;
+
                bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
                return;
 
@@ -793,6 +833,7 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
                 */
                fabric->bport.port_topo.pn2n.rem_port_wwn =
                        fabric->lps->pr_pwwn;
+               fabric->fab_type = BFA_FCS_FABRIC_N2N;
                bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
        }
 
@@ -808,13 +849,17 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
 {
        struct bfa_s            *bfa = fabric->fcs->bfa;
        struct bfa_lport_cfg_s  *pcfg = &fabric->bport.port_cfg;
-       u8                      alpa = 0;
+       u8                      alpa = 0, bb_scn = 0;
 
        if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
                alpa = bfa_fcport_get_myalpa(bfa);
 
+       if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
+           (!fabric->fcs->bbscn_flogi_rjt))
+               bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
+
        bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
-                     pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
+                     pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);
 
        fabric->stats.flogi_sent++;
 }
@@ -873,6 +918,40 @@ bfa_fcs_fabric_delay(void *cbarg)
 }
 
 /*
+ * Computes operating BB_SCN value
+ */
+static u8
+bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
+{
+       u8      pr_bbscn = fabric->lps->pr_bbscn;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
+
+       if (!(fcport->cfg.bb_scn_state && pr_bbscn))
+               return 0;
+
+       /* return max of local/remote bb_scn values */
+       return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
+               pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
+}
+
+/*
+ * Check if BB_SCN can be enabled.
+ */
+static bfa_boolean_t
+bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
+
+       if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
+                       fcport->cfg.bb_scn_state &&
+                       !bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
+                       !bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
+               return BFA_TRUE;
+       else
+               return BFA_FALSE;
+}
+
+/*
  * Delete all vports and wait for vport delete completions.
  */
 static void
@@ -989,6 +1068,7 @@ void
 bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
 {
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
        bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
 }
 
@@ -1192,6 +1272,7 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
        }
 
        fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
+       fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
        bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
        bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
 
@@ -1224,9 +1305,10 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
                                    n2n_port->reply_oxid, pcfg->pwwn,
                                    pcfg->nwwn,
                                    bfa_fcport_get_maxfrsize(bfa),
-                                   bfa_fcport_get_rx_bbcredit(bfa));
+                                   bfa_fcport_get_rx_bbcredit(bfa),
+                                   bfa_fcs_fabric_oper_bbscn(fabric));
 
-       bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
+       bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,
                      BFA_FALSE, FC_CLASS_3,
                      reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
                      FC_MAX_PDUSZ, 0);
@@ -1298,6 +1380,45 @@ bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
 }
 
 /*
+ *     Return the list of local logical ports present in the given VF.
+ *
+ *     @param[in]      vf      vf for which logical ports are returned
+ *     @param[out]     lpwwn   returned logical port wwn list
+ *     @param[in,out]  nlports in:size of lpwwn list;
+ *                             out:total elements present,
+ *                             actual elements returned is limited by the size
+ */
+void
+bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
+{
+       struct list_head *qe;
+       struct bfa_fcs_vport_s *vport;
+       int     i = 0;
+       struct bfa_fcs_s        *fcs;
+
+       if (vf == NULL || lpwwn == NULL || *nlports == 0)
+               return;
+
+       fcs = vf->fcs;
+
+       bfa_trc(fcs, vf->vf_id);
+       bfa_trc(fcs, (uint32_t) *nlports);
+
+       lpwwn[i++] = vf->bport.port_cfg.pwwn;
+
+       list_for_each(qe, &vf->vport_q) {
+               if (i >= *nlports)
+                       break;
+
+               vport = (struct bfa_fcs_vport_s *) qe;
+               lpwwn[i++] = vport->lport.port_cfg.pwwn;
+       }
+
+       bfa_trc(fcs, i);
+       *nlports = i;
+}
+
+/*
  * BFA FCS PPORT ( physical port)
  */
 static void
index 61cdce4..a5f1faf 100644 (file)
@@ -254,6 +254,9 @@ struct bfa_fcs_fabric_s;
 #define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ                        48
 #define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ               16
 
+/* bb_scn value in 2^bb_scn */
+#define BFA_FCS_PORT_DEF_BB_SCN                                3
+
 /*
  * Get FC port ID for a logical port.
  */
@@ -379,6 +382,7 @@ 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_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)
@@ -420,6 +424,7 @@ struct bfa_fcs_rport_s {
        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  */
@@ -447,6 +452,8 @@ bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *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(
@@ -591,10 +598,21 @@ void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
 void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
                        struct fchs_s *fchs, u16 len);
 
-#define        BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  |   \
-                                      FDMI_TRANS_SPEED_2G |    \
-                                      FDMI_TRANS_SPEED_4G |    \
-                                      FDMI_TRANS_SPEED_8G)
+#define BFA_FCS_FDMI_SUPP_SPEEDS_4G    (FDMI_TRANS_SPEED_1G  | \
+                               FDMI_TRANS_SPEED_2G |           \
+                               FDMI_TRANS_SPEED_4G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_8G    (FDMI_TRANS_SPEED_1G  | \
+                               FDMI_TRANS_SPEED_2G |           \
+                               FDMI_TRANS_SPEED_4G |           \
+                               FDMI_TRANS_SPEED_8G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_16G   (FDMI_TRANS_SPEED_2G  | \
+                               FDMI_TRANS_SPEED_4G |           \
+                               FDMI_TRANS_SPEED_8G |           \
+                               FDMI_TRANS_SPEED_16G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_10G   FDMI_TRANS_SPEED_10G
 
 /*
  * HBA Attribute Block : BFA internal representation. Note : Some variable
@@ -649,6 +667,8 @@ struct bfa_fcs_s {
        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   bbscn_enabled;  /*  Driver Config Parameter */
+       bfa_boolean_t   bbscn_flogi_rjt;/*  FLOGI reject due to BB_SCN */
        bfa_boolean_t min_cfg;          /* min cfg enabled/disabled */
        u16     port_vfid;      /*  port default VF ID */
        struct bfa_fcs_driver_info_s driver_info;
@@ -715,6 +735,8 @@ 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);
@@ -723,6 +745,7 @@ void bfa_fcs_exit(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
index e7b49f4..29b4108 100644 (file)
@@ -54,6 +54,7 @@ enum bfa_fcs_itnim_event {
        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 */
 };
 
 static void    bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
@@ -178,6 +179,10 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
                                BFA_FCS_RETRY_TIMEOUT);
                break;
 
+       case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               break;
+
        case BFA_FCS_ITNIM_SM_OFFLINE:
                bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
                bfa_fcxp_discard(itnim->fcxp);
@@ -447,6 +452,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
                                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;
@@ -472,6 +478,10 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
                bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
 
                itnim->stats.prli_rsp_rjt++;
+               if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
+                       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);
+                       return;
+               }
                bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
        }
 }
index 1d6be8c..f8251a9 100644 (file)
@@ -74,6 +74,7 @@ enum bfa_fcs_lport_event {
        BFA_FCS_PORT_SM_OFFLINE = 3,
        BFA_FCS_PORT_SM_DELETE = 4,
        BFA_FCS_PORT_SM_DELRPORT = 5,
+       BFA_FCS_PORT_SM_STOP = 6,
 };
 
 static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
@@ -86,6 +87,8 @@ static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
                                        enum bfa_fcs_lport_event event);
 static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
                                        enum bfa_fcs_lport_event event);
+static void    bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+                                       enum bfa_fcs_lport_event event);
 
 static void
 bfa_fcs_lport_sm_uninit(
@@ -123,6 +126,12 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
                bfa_fcs_lport_deleted(port);
                break;
 
+       case BFA_FCS_PORT_SM_STOP:
+               /* If vport - send completion call back */
+               if (port->vport)
+                       bfa_fcs_vport_stop_comp(port->vport);
+               break;
+
        case BFA_FCS_PORT_SM_OFFLINE:
                break;
 
@@ -148,6 +157,23 @@ bfa_fcs_lport_sm_online(
                bfa_fcs_lport_offline_actions(port);
                break;
 
+       case BFA_FCS_PORT_SM_STOP:
+               __port_action[port->fabric->fab_type].offline(port);
+
+               if (port->num_rports == 0) {
+                       bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+                       /* If vport - send completion call back */
+                       if (port->vport)
+                               bfa_fcs_vport_stop_comp(port->vport);
+               } else {
+                       bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+                       list_for_each_safe(qe, qen, &port->rport_q) {
+                               rport = (struct bfa_fcs_rport_s *) qe;
+                               bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+                       }
+               }
+               break;
+
        case BFA_FCS_PORT_SM_DELETE:
 
                __port_action[port->fabric->fab_type].offline(port);
@@ -189,6 +215,21 @@ bfa_fcs_lport_sm_offline(
                bfa_fcs_lport_online_actions(port);
                break;
 
+       case BFA_FCS_PORT_SM_STOP:
+               if (port->num_rports == 0) {
+                       bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+                       /* If vport - send completion call back */
+                       if (port->vport)
+                               bfa_fcs_vport_stop_comp(port->vport);
+               } else {
+                       bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+                       list_for_each_safe(qe, qen, &port->rport_q) {
+                               rport = (struct bfa_fcs_rport_s *) qe;
+                               bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+                       }
+               }
+               break;
+
        case BFA_FCS_PORT_SM_DELETE:
                if (port->num_rports == 0) {
                        bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
@@ -212,6 +253,28 @@ bfa_fcs_lport_sm_offline(
 }
 
 static void
+bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+                         enum bfa_fcs_lport_event event)
+{
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_PORT_SM_DELRPORT:
+               if (port->num_rports == 0) {
+                       bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+                       /* If vport - send completion call back */
+                       if (port->vport)
+                               bfa_fcs_vport_stop_comp(port->vport);
+               }
+               break;
+
+       default:
+               bfa_sm_fault(port->fcs, event);
+       }
+}
+
+static void
 bfa_fcs_lport_sm_deleting(
        struct bfa_fcs_lport_s *port,
        enum bfa_fcs_lport_event event)
@@ -265,6 +328,40 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 }
 
 /*
+ * Send a FCCT Reject
+ */
+static void
+bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
+       struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl)
+{
+       struct fchs_s   fchs;
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_rport_s *bfa_rport = NULL;
+       int             len;
+       struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1);
+       struct ct_hdr_s *ct_hdr;
+
+       bfa_trc(port->fcs, rx_fchs->d_id);
+       bfa_trc(port->fcs, rx_fchs->s_id);
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       ct_hdr = bfa_fcxp_get_reqbuf(fcxp);
+       ct_hdr->gs_type = rx_cthdr->gs_type;
+       ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type;
+
+       len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id,
+                       bfa_fcs_lport_get_fcid(port),
+                       rx_fchs->ox_id, reason_code, reason_code_expl);
+
+       bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+                       BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+                       FC_MAX_PDUSZ, 0);
+}
+
+/*
  * Process incoming plogi from a remote port.
  */
 static void
@@ -647,6 +744,16 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
                        bfa_fcs_lport_abts_acc(lport, fchs);
                return;
        }
+
+       if (fchs->type == FC_TYPE_SERVICES) {
+               /*
+                * Unhandled FC-GS frames. Send a FC-CT Reject
+                */
+               bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP,
+                               CT_NS_EXP_NOADDITIONAL);
+               return;
+       }
+
        /*
         * look for a matching remote port ID
         */
@@ -835,8 +942,8 @@ bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
        lport->fcs = fcs;
        lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
        lport->vport = vport;
-       lport->lp_tag = (vport) ? vport->lps->lp_tag :
-                                 lport->fabric->lps->lp_tag;
+       lport->lp_tag = (vport) ? vport->lps->bfa_tag :
+                                 lport->fabric->lps->bfa_tag;
 
        INIT_LIST_HEAD(&lport->rport_q);
        lport->num_rports = 0;
@@ -1074,6 +1181,8 @@ static void       bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
                                 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
 static void    bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
                                  struct bfa_fcs_fdmi_port_attr_s *port_attr);
+u32    bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed);
+
 /*
  *  fcs_fdmi_sm FCS FDMI state machine
  */
@@ -1672,7 +1781,7 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
        memcpy(attr->value, fcs_hba_attr->driver_version, templen);
        templen = fc_roundup(templen, sizeof(u32));
        curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
-       len += templen;;
+       len += templen;
        count++;
        attr->len = cpu_to_be16(templen + sizeof(attr->type) +
                             sizeof(templen));
@@ -2160,12 +2269,36 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
        /*
         * Supported Speeds
         */
-       port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
+       switch (pport_attr.speed_supported) {
+       case BFA_PORT_SPEED_16GBPS:
+               port_attr->supp_speed =
+                       cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
+               break;
+
+       case BFA_PORT_SPEED_10GBPS:
+               port_attr->supp_speed =
+                       cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
+               break;
+
+       case BFA_PORT_SPEED_8GBPS:
+               port_attr->supp_speed =
+                       cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
+               break;
+
+       case BFA_PORT_SPEED_4GBPS:
+               port_attr->supp_speed =
+                       cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
+               break;
+
+       default:
+               bfa_sm_fault(port->fcs, pport_attr.speed_supported);
+       }
 
        /*
         * Current Speed
         */
-       port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
+       port_attr->curr_speed = cpu_to_be32(
+                               bfa_fcs_fdmi_convert_speed(pport_attr.speed));
 
        /*
         * Max PDU Size.
@@ -2186,6 +2319,41 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 
 }
 
+/*
+ * Convert BFA speed to FDMI format.
+ */
+u32
+bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
+{
+       u32     ret;
+
+       switch (pport_speed) {
+       case BFA_PORT_SPEED_1GBPS:
+       case BFA_PORT_SPEED_2GBPS:
+               ret = pport_speed;
+               break;
+
+       case BFA_PORT_SPEED_4GBPS:
+               ret = FDMI_TRANS_SPEED_4G;
+               break;
+
+       case BFA_PORT_SPEED_8GBPS:
+               ret = FDMI_TRANS_SPEED_8G;
+               break;
+
+       case BFA_PORT_SPEED_10GBPS:
+               ret = FDMI_TRANS_SPEED_10G;
+               break;
+
+       case BFA_PORT_SPEED_16GBPS:
+               ret = FDMI_TRANS_SPEED_16G;
+               break;
+
+       default:
+               ret = FDMI_TRANS_SPEED_UNKNOWN;
+       }
+       return ret;
+}
 
 void
 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
@@ -2829,7 +2997,8 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
                             bfa_hton3b(FC_MGMT_SERVER),
                             bfa_fcs_lport_get_fcid(port), 0,
                             port->port_cfg.pwwn, port->port_cfg.nwwn,
-                                bfa_fcport_get_maxfrsize(port->fcs->bfa));
+                            bfa_fcport_get_maxfrsize(port->fcs->bfa),
+                            bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
                          FC_CLASS_3, len, &fchs,
@@ -3573,7 +3742,7 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
        bfa_trc(port->fcs, port->pid);
 
-fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
        if (!fcxp) {
                port->stats.ns_plogi_alloc_wait++;
                bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
@@ -3586,7 +3755,8 @@ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
                             bfa_hton3b(FC_NAME_SERVER),
                             bfa_fcs_lport_get_fcid(port), 0,
                             port->port_cfg.pwwn, port->port_cfg.nwwn,
-                                bfa_fcport_get_maxfrsize(port->fcs->bfa));
+                            bfa_fcport_get_maxfrsize(port->fcs->bfa),
+                            bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
                          FC_CLASS_3, len, &fchs,
@@ -4762,8 +4932,8 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
        while (qe != qh) {
                rport = (struct bfa_fcs_rport_s *) qe;
                if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
-                       (bfa_fcs_rport_get_state(rport) ==
-                         BFA_RPORT_OFFLINE)) {
+                       (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
+                       (rport->scsi_function != BFA_RPORT_TARGET)) {
                        qe = bfa_q_next(qe);
                        continue;
                }
@@ -4776,17 +4946,15 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
                                bfa_fcport_get_ratelim_speed(port->fcs->bfa);
                }
 
-               if      ((rport_speed  == BFA_PORT_SPEED_8GBPS) ||
-                       (rport_speed > port_speed)) {
+               if (rport_speed > max_speed)
                        max_speed = rport_speed;
-                       break;
-               } else if (rport_speed > max_speed) {
-                       max_speed = rport_speed;
-               }
 
                qe = bfa_q_next(qe);
        }
 
+       if (max_speed > port_speed)
+               max_speed = port_speed;
+
        bfa_trc(fcs, max_speed);
        return max_speed;
 }
@@ -4918,6 +5086,7 @@ enum bfa_fcs_vport_event {
        BFA_FCS_VPORT_SM_DELCOMP = 11,  /*  lport delete completion */
        BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,      /*  Dup wnn error*/
        BFA_FCS_VPORT_SM_RSP_FAILED = 13,       /*  non-retryable failure */
+       BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
 };
 
 static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
@@ -4930,6 +5099,8 @@ static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
                                       enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
                                             enum bfa_fcs_vport_event event);
+static void    bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
+                                       enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
                                        enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
@@ -4940,6 +5111,10 @@ static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
                                      enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
                                      enum bfa_fcs_vport_event event);
+static void    bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+                                       enum bfa_fcs_vport_event event);
+static void    bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+                                       enum bfa_fcs_vport_event event);
 
 static struct bfa_sm_table_s  vport_sm_table[] = {
        {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
@@ -4947,6 +5122,7 @@ static struct bfa_sm_table_s  vport_sm_table[] = {
        {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
        {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
        {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
+       {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
        {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
        {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
        {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
@@ -5042,6 +5218,11 @@ bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
                bfa_fcs_vport_do_fdisc(vport);
                break;
 
+       case BFA_FCS_VPORT_SM_STOP:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+               bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+               break;
+
        case BFA_FCS_VPORT_SM_OFFLINE:
                /*
                 * This can happen if the vport couldn't be initialzied
@@ -5070,9 +5251,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
 
        switch (event) {
        case BFA_FCS_VPORT_SM_DELETE:
-               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-               bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
-               bfa_fcs_lport_delete(&vport->lport);
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
                break;
 
        case BFA_FCS_VPORT_SM_OFFLINE:
@@ -5140,6 +5319,41 @@ bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
 }
 
 /*
+ * FDISC is in progress and we got a vport delete request -
+ * this is a wait state while we wait for fdisc response and
+ * we will transition to the appropriate state - on rsp status.
+ */
+static void
+bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
+                               enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_RSP_OK:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
+               bfa_fcs_lport_delete(&vport->lport);
+               break;
+
+       case BFA_FCS_VPORT_SM_DELETE:
+               break;
+
+       case BFA_FCS_VPORT_SM_OFFLINE:
+       case BFA_FCS_VPORT_SM_RSP_ERROR:
+       case BFA_FCS_VPORT_SM_RSP_FAILED:
+       case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+               bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
+               bfa_fcs_lport_delete(&vport->lport);
+               break;
+
+       default:
+               bfa_sm_fault(__vport_fcs(vport), event);
+       }
+}
+
+/*
  * Vport is online (FDISC is complete).
  */
 static void
@@ -5155,6 +5369,11 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
                bfa_fcs_lport_delete(&vport->lport);
                break;
 
+       case BFA_FCS_VPORT_SM_STOP:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
+               bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+               break;
+
        case BFA_FCS_VPORT_SM_OFFLINE:
                bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
                bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
@@ -5167,6 +5386,32 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
 }
 
 /*
+ * Vport is being stopped - awaiting lport stop completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+                         enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_STOPCOMP:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
+               bfa_fcs_vport_do_logo(vport);
+               break;
+
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+               break;
+
+       default:
+               bfa_sm_fault(__vport_fcs(vport), event);
+       }
+}
+
+/*
  * Vport is being deleted - awaiting lport delete completion to send
  * LOGO to fabric.
  */
@@ -5236,6 +5481,10 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
                bfa_fcs_vport_free(vport);
                break;
 
+       case BFA_FCS_VPORT_SM_STOPCOMP:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+               break;
+
        case BFA_FCS_VPORT_SM_DELETE:
                break;
 
@@ -5245,6 +5494,34 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
 }
 
 /*
+ * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+                              enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
+               /*
+                * !!! fall through !!!
+                */
+
+       case BFA_FCS_VPORT_SM_RSP_OK:
+       case BFA_FCS_VPORT_SM_RSP_ERROR:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+               break;
+
+       default:
+               bfa_sm_fault(__vport_fcs(vport), event);
+       }
+}
+
+/*
  * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
  * is done.
  */
@@ -5391,7 +5668,10 @@ void
 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
 {
        vport->vport_stats.fab_online++;
-       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+       if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
+               bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+       else
+               vport->vport_stats.fab_no_npiv++;
 }
 
 /*
@@ -5422,6 +5702,15 @@ bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
 }
 
 /*
+ * Stop completion callback from associated lport
+ */
+void
+bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
+{
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
+}
+
+/*
  * Delete completion callback from associated lport
  */
 void
index caaee6f..2c51445 100644 (file)
@@ -262,6 +262,7 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
+       case RPSM_EVENT_PLOGI_COMP:
        case RPSM_EVENT_SCN:
                /*
                 * Ignore, SCN is possibly online notification.
@@ -470,6 +471,7 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
                break;
 
        case RPSM_EVENT_PRLO_RCVD:
+       case RPSM_EVENT_PLOGI_COMP:
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
@@ -484,9 +486,9 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               rport->plogi_pending = BFA_TRUE;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
                bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
-               bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
        case RPSM_EVENT_DELETE:
@@ -891,6 +893,18 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
 
        switch (event) {
        case RPSM_EVENT_HCB_OFFLINE:
+               if (bfa_fcs_lport_is_online(rport->port) &&
+                   (rport->plogi_pending)) {
+                       rport->plogi_pending = BFA_FALSE;
+                       bfa_sm_set_state(rport,
+                               bfa_fcs_rport_sm_plogiacc_sending);
+                       bfa_fcs_rport_send_plogiacc(rport, NULL);
+                       break;
+               }
+               /*
+                * !! fall through !!
+                */
+
        case RPSM_EVENT_ADDRESS_CHANGE:
                if (bfa_fcs_lport_is_online(rport->port)) {
                        if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
@@ -921,6 +935,8 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
        case RPSM_EVENT_SCN:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
+       case RPSM_EVENT_PLOGI_RCVD:
+       case RPSM_EVENT_LOGO_IMP:
                /*
                 * Ignore, already offline.
                 */
@@ -957,10 +973,18 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
                 */
                if (bfa_fcs_lport_is_online(rport->port) &&
                        (!BFA_FCS_PID_IS_WKA(rport->pid))) {
-                       bfa_sm_set_state(rport,
-                               bfa_fcs_rport_sm_nsdisc_sending);
-                       rport->ns_retries = 0;
-                       bfa_fcs_rport_send_nsdisc(rport, NULL);
+                       if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_nsdisc_sending);
+                               rport->ns_retries = 0;
+                               bfa_fcs_rport_send_nsdisc(rport, NULL);
+                       } else {
+                               /* For N2N  Direct Attach, try to re-login */
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_plogi_sending);
+                               rport->plogi_retries = 0;
+                               bfa_fcs_rport_send_plogi(rport, NULL);
+                       }
                } else {
                        /*
                         * if it is not a well known address, reset the
@@ -1356,7 +1380,8 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
        len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
                                bfa_fcs_lport_get_fcid(port), 0,
                                port->port_cfg.pwwn, port->port_cfg.nwwn,
-                               bfa_fcport_get_maxfrsize(port->fcs->bfa));
+                               bfa_fcport_get_maxfrsize(port->fcs->bfa),
+                               bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
                        FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
@@ -1476,7 +1501,8 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
                                 rport->pid, bfa_fcs_lport_get_fcid(port),
                                 rport->reply_oxid, port->port_cfg.pwwn,
                                 port->port_cfg.nwwn,
-                                bfa_fcport_get_maxfrsize(port->fcs->bfa));
+                                bfa_fcport_get_maxfrsize(port->fcs->bfa),
+                                bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
        bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
                        FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
@@ -2024,6 +2050,11 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
 
        rport->stats.onlines++;
 
+       if ((!rport->pid) || (!rport->pwwn)) {
+               bfa_trc(rport->fcs, rport->pid);
+               bfa_sm_fault(rport->fcs, rport->pid);
+       }
+
        if (bfa_fcs_lport_is_initiator(port)) {
                bfa_fcs_itnim_rport_online(rport->itnim);
                if (!BFA_FCS_PID_IS_WKA(rport->pid))
@@ -2047,6 +2078,7 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
        char    rpwwn_buf[BFA_STRING_32];
 
        rport->stats.offlines++;
+       rport->plogi_pending = BFA_FALSE;
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
        wwn2str(rpwwn_buf, rport->pwwn);
@@ -2120,7 +2152,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
 
                port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
                bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
-                                         port->fabric->bb_credit);
+                                         port->fabric->bb_credit, 0);
        }
 
 }
@@ -2233,22 +2265,6 @@ bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
        bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
 }
 
-static int
-wwn_compare(wwn_t wwn1, wwn_t wwn2)
-{
-       u8              *b1 = (u8 *) &wwn1;
-       u8              *b2 = (u8 *) &wwn2;
-       int             i;
-
-       for (i = 0; i < sizeof(wwn_t); i++) {
-               if (b1[i] < b2[i])
-                       return -1;
-               if (b1[i] > b2[i])
-                       return 1;
-       }
-       return 0;
-}
-
 /*
  *     Called by bport/vport to handle PLOGI received from an existing
  *      remote port.
@@ -2266,19 +2282,8 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
        rport->reply_oxid = rx_fchs->ox_id;
        bfa_trc(rport->fcs, rport->reply_oxid);
 
-       /*
-        * In Switched fabric topology,
-        * PLOGI to each other. If our pwwn is smaller, ignore it,
-        * if it is not a well known address.
-        * If the link topology is N2N,
-        * this Plogi should be accepted.
-        */
-       if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
-               (bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
-               (!BFA_FCS_PID_IS_WKA(rport->pid))) {
-               bfa_trc(rport->fcs, rport->pid);
-               return;
-       }
+       rport->pid = rx_fchs->s_id;
+       bfa_trc(rport->fcs, rport->pid);
 
        rport->stats.plogi_rcvd++;
        bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
@@ -2531,7 +2536,45 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
        bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
 }
 
-
+void
+bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+               struct bfa_rport_attr_s *rport_attr)
+{
+       struct bfa_rport_qos_attr_s qos_attr;
+       struct bfa_fcs_lport_s *port = rport->port;
+       bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+
+       memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
+       memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
+
+       rport_attr->pid = rport->pid;
+       rport_attr->pwwn = rport->pwwn;
+       rport_attr->nwwn = rport->nwwn;
+       rport_attr->cos_supported = rport->fc_cos;
+       rport_attr->df_sz = rport->maxfrsize;
+       rport_attr->state = bfa_fcs_rport_get_state(rport);
+       rport_attr->fc_cos = rport->fc_cos;
+       rport_attr->cisc = rport->cisc;
+       rport_attr->scsi_function = rport->scsi_function;
+       rport_attr->curr_speed  = rport->rpf.rpsc_speed;
+       rport_attr->assigned_speed  = rport->rpf.assigned_speed;
+
+       qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
+       qos_attr.qos_flow_id =
+               cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
+       rport_attr->qos_attr = qos_attr;
+
+       rport_attr->trl_enforced = BFA_FALSE;
+       if (bfa_fcport_is_ratelim(port->fcs->bfa) &&
+           (rport->scsi_function == BFA_RPORT_TARGET)) {
+               if (rport_speed == BFA_PORT_SPEED_UNKNOWN)
+                       rport_speed =
+                               bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
+
+               if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+                       rport_attr->trl_enforced = BFA_TRUE;
+       }
+}
 
 /*
  * Remote port implementation.
index 977e681..e7ffd82 100644 (file)
 
 #include "bfad_drv.h"
 #include "bfa_modules.h"
-#include "bfi_cbreg.h"
+#include "bfi_reg.h"
 
 void
 bfa_hwcb_reginit(struct bfa_s *bfa)
 {
        struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
        void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
-       int                     i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+       int     fn = bfa_ioc_pcifn(&bfa->ioc);
 
        if (fn == 0) {
                bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -33,29 +33,6 @@ bfa_hwcb_reginit(struct bfa_s *bfa)
                bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
                bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
        }
-
-       for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
-               /*
-                * CPE registers
-                */
-               q = CPE_Q_NUM(fn, i);
-               bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q));
-               bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q));
-               bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q));
-
-               /*
-                * RME registers
-                */
-               q = CPE_Q_NUM(fn, i);
-               bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q));
-               bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q));
-               bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q));
-       }
-}
-
-void
-bfa_hwcb_reqq_ack(struct bfa_s *bfa, int reqq)
-{
 }
 
 static void
@@ -65,11 +42,6 @@ bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
                        bfa->iocfc.bfa_regs.intr_status);
 }
 
-void
-bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq)
-{
-}
-
 static void
 bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq)
 {
@@ -104,43 +76,71 @@ bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
 }
 
 /*
+ * Dummy interrupt handler for handling spurious interrupts.
+ */
+static void
+bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec)
+{
+}
+
+/*
  * No special setup required for crossbow -- vector assignments are implicit.
  */
 void
 bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
 {
-       int i;
-
        WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
 
        bfa->msix.nvecs = nvecs;
-       if (nvecs == 1) {
-               for (i = 0; i < BFA_MSIX_CB_MAX; i++)
+       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 = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++)
-               bfa->msix.handler[i] = bfa_msix_reqq;
-
-       for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++)
-               bfa->msix.handler[i] = bfa_msix_rspq;
-
-       for (; i < BFA_MSIX_CB_MAX; i++)
+       for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
                bfa->msix.handler[i] = bfa_msix_lpu_err;
 }
 
-/*
- * Crossbow -- dummy, interrupts are masked
- */
 void
-bfa_hwcb_msix_install(struct bfa_s *bfa)
+bfa_hwcb_msix_queue_install(struct bfa_s *bfa)
 {
+       int i;
+
+       if (bfa->msix.nvecs == 0)
+               return;
+
+       if (bfa->msix.nvecs == 1) {
+               for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
+                       bfa->msix.handler[i] = bfa_msix_all;
+               return;
+       }
+
+       for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++)
+               bfa->msix.handler[i] = bfa_msix_reqq;
+
+       for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
+               bfa->msix.handler[i] = bfa_msix_rspq;
 }
 
 void
 bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
 {
+       int i;
+
+       for (i = 0; i < BFI_MSIX_CB_MAX; i++)
+               bfa->msix.handler[i] = bfa_hwcb_msix_dummy;
 }
 
 /*
@@ -156,6 +156,6 @@ bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
 void
 bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
 {
-       *start = BFA_MSIX_RME_Q0;
-       *end = BFA_MSIX_RME_Q7;
+       *start = BFI_MSIX_RME_QMIN_CB;
+       *end = BFI_MSIX_RME_QMAX_CB;
 }
index 21018d9..989bbce 100644 (file)
 
 #include "bfad_drv.h"
 #include "bfa_modules.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 
 BFA_TRC_FILE(HAL, IOCFC_CT);
 
-static u32 __ct_msix_err_vec_reg[] = {
-       HOST_MSIX_ERR_INDEX_FN0,
-       HOST_MSIX_ERR_INDEX_FN1,
-       HOST_MSIX_ERR_INDEX_FN2,
-       HOST_MSIX_ERR_INDEX_FN3,
-};
-
-static void
-bfa_hwct_msix_lpu_err_set(struct bfa_s *bfa, bfa_boolean_t msix, int vec)
-{
-       int fn = bfa_ioc_pcifn(&bfa->ioc);
-       void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
-
-       if (msix)
-               writel(vec, kva + __ct_msix_err_vec_reg[fn]);
-       else
-               writel(0, kva + __ct_msix_err_vec_reg[fn]);
-}
-
 /*
  * Dummy interrupt handler for handling spurious interrupt during chip-reinit.
  */
@@ -53,7 +34,7 @@ bfa_hwct_reginit(struct bfa_s *bfa)
 {
        struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
        void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
-       int                     i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+       int     fn = bfa_ioc_pcifn(&bfa->ioc);
 
        if (fn == 0) {
                bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -62,26 +43,16 @@ bfa_hwct_reginit(struct bfa_s *bfa)
                bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
                bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
        }
+}
 
-       for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
-               /*
-                * CPE registers
-                */
-               q = CPE_Q_NUM(fn, i);
-               bfa_regs->cpe_q_pi[i] = (kva + CPE_PI_PTR_Q(q << 5));
-               bfa_regs->cpe_q_ci[i] = (kva + CPE_CI_PTR_Q(q << 5));
-               bfa_regs->cpe_q_depth[i] = (kva + CPE_DEPTH_Q(q << 5));
-               bfa_regs->cpe_q_ctrl[i] = (kva + CPE_QCTRL_Q(q << 5));
-
-               /*
-                * RME registers
-                */
-               q = CPE_Q_NUM(fn, i);
-               bfa_regs->rme_q_pi[i] = (kva + RME_PI_PTR_Q(q << 5));
-               bfa_regs->rme_q_ci[i] = (kva + RME_CI_PTR_Q(q << 5));
-               bfa_regs->rme_q_depth[i] = (kva + RME_DEPTH_Q(q << 5));
-               bfa_regs->rme_q_ctrl[i] = (kva + RME_QCTRL_Q(q << 5));
-       }
+void
+bfa_hwct2_reginit(struct bfa_s *bfa)
+{
+       struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
+       void __iomem    *kva = bfa_ioc_bar0(&bfa->ioc);
+
+       bfa_regs->intr_status = (kva + CT2_HOSTFN_INT_STATUS);
+       bfa_regs->intr_mask   = (kva + CT2_HOSTFN_INTR_MASK);
 }
 
 void
@@ -106,9 +77,9 @@ void
 bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
                 u32 *num_vecs, u32 *max_vec_bit)
 {
-       *msix_vecs_bmap = (1 << BFA_MSIX_CT_MAX) - 1;
-       *max_vec_bit = (1 << (BFA_MSIX_CT_MAX - 1));
-       *num_vecs = BFA_MSIX_CT_MAX;
+       *msix_vecs_bmap = (1 << BFI_MSIX_CT_MAX) - 1;
+       *max_vec_bit = (1 << (BFI_MSIX_CT_MAX - 1));
+       *num_vecs = BFI_MSIX_CT_MAX;
 }
 
 /*
@@ -117,7 +88,7 @@ bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
 void
 bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
 {
-       WARN_ON((nvecs != 1) && (nvecs != BFA_MSIX_CT_MAX));
+       WARN_ON((nvecs != 1) && (nvecs != BFI_MSIX_CT_MAX));
        bfa_trc(bfa, nvecs);
 
        bfa->msix.nvecs = nvecs;
@@ -125,7 +96,19 @@ bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
 }
 
 void
-bfa_hwct_msix_install(struct bfa_s *bfa)
+bfa_hwct_msix_ctrl_install(struct bfa_s *bfa)
+{
+       if (bfa->msix.nvecs == 0)
+               return;
+
+       if (bfa->msix.nvecs == 1)
+               bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_all;
+       else
+               bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_lpu_err;
+}
+
+void
+bfa_hwct_msix_queue_install(struct bfa_s *bfa)
 {
        int i;
 
@@ -133,19 +116,16 @@ bfa_hwct_msix_install(struct bfa_s *bfa)
                return;
 
        if (bfa->msix.nvecs == 1) {
-               for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+               for (i = BFI_MSIX_CPE_QMIN_CT; i < BFI_MSIX_CT_MAX; i++)
                        bfa->msix.handler[i] = bfa_msix_all;
                return;
        }
 
-       for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q3; i++)
+       for (i = BFI_MSIX_CPE_QMIN_CT; i <= BFI_MSIX_CPE_QMAX_CT; i++)
                bfa->msix.handler[i] = bfa_msix_reqq;
 
-       for (; i <= BFA_MSIX_RME_Q3; i++)
+       for (i = BFI_MSIX_RME_QMIN_CT; i <= BFI_MSIX_RME_QMAX_CT; i++)
                bfa->msix.handler[i] = bfa_msix_rspq;
-
-       WARN_ON(i != BFA_MSIX_LPU_ERR);
-       bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;
 }
 
 void
@@ -153,7 +133,7 @@ bfa_hwct_msix_uninstall(struct bfa_s *bfa)
 {
        int i;
 
-       for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+       for (i = 0; i < BFI_MSIX_CT_MAX; i++)
                bfa->msix.handler[i] = bfa_hwct_msix_dummy;
 }
 
@@ -164,13 +144,12 @@ void
 bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
 {
        bfa_trc(bfa, 0);
-       bfa_hwct_msix_lpu_err_set(bfa, msix, BFA_MSIX_LPU_ERR);
        bfa_ioc_isr_mode_set(&bfa->ioc, msix);
 }
 
 void
 bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
 {
-       *start = BFA_MSIX_RME_Q0;
-       *end = BFA_MSIX_RME_Q3;
+       *start = BFI_MSIX_RME_QMIN_CT;
+       *end = BFI_MSIX_RME_QMAX_CT;
 }
index 6c7e033..d6c2bf3 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "bfad_drv.h"
 #include "bfa_ioc.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 #include "bfa_defs.h"
 #include "bfa_defs_svc.h"
 
@@ -29,8 +29,8 @@ BFA_TRC_FILE(CNA, IOC);
 #define BFA_IOC_TOV            3000    /* msecs */
 #define BFA_IOC_HWSEM_TOV      500     /* msecs */
 #define BFA_IOC_HB_TOV         500     /* msecs */
-#define BFA_IOC_HWINIT_MAX     5
 #define BFA_IOC_TOV_RECOVER     BFA_IOC_HB_TOV
+#define BFA_IOC_POLL_TOV       BFA_TIMER_FREQ
 
 #define bfa_ioc_timer_start(__ioc)                                     \
        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,        \
@@ -79,14 +79,17 @@ bfa_boolean_t bfa_auto_recover = BFA_TRUE;
 static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
 static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
 static void bfa_ioc_timeout(void *ioc);
+static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
 static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
 static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);
 static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
 static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
+static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
+                               enum bfa_ioc_event_e event);
 static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
 static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
 static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
@@ -105,11 +108,12 @@ enum ioc_event {
        IOC_E_ENABLED           = 5,    /*  f/w enabled         */
        IOC_E_FWRSP_GETATTR     = 6,    /*  IOC get attribute response  */
        IOC_E_DISABLED          = 7,    /*  f/w disabled                */
-       IOC_E_INITFAILED        = 8,    /*  failure notice by iocpf sm  */
-       IOC_E_PFFAILED          = 9,    /*  failure notice by iocpf sm  */
-       IOC_E_HBFAIL            = 10,   /*  heartbeat failure           */
-       IOC_E_HWERROR           = 11,   /*  hardware error interrupt    */
-       IOC_E_TIMEOUT           = 12,   /*  timeout                     */
+       IOC_E_PFFAILED          = 8,    /*  failure notice by iocpf sm  */
+       IOC_E_HBFAIL            = 9,    /*  heartbeat failure           */
+       IOC_E_HWERROR           = 10,   /*  hardware error interrupt    */
+       IOC_E_TIMEOUT           = 11,   /*  timeout                     */
+       IOC_E_HWFAILED          = 12,   /*  PCI mapping failure notice  */
+       IOC_E_FWRSP_ACQ_ADDR    = 13,   /*  Acquiring address           */
 };
 
 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
@@ -121,6 +125,8 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, acq_addr, struct bfa_ioc_s, enum ioc_event);
 
 static struct bfa_sm_table_s ioc_sm_table[] = {
        {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -132,6 +138,8 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
        {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
        {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
        {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+       {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
+       {BFA_SM(bfa_ioc_sm_acq_addr), BFA_IOC_ACQ_ADDR},
 };
 
 /*
@@ -143,9 +151,9 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
                        bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
 #define bfa_iocpf_timer_stop(__ioc)    bfa_timer_stop(&(__ioc)->ioc_timer)
 
-#define bfa_iocpf_recovery_timer_start(__ioc)                          \
+#define bfa_iocpf_poll_timer_start(__ioc)                              \
        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,        \
-                       bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
+                       bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)
 
 #define bfa_sem_timer_start(__ioc)                                     \
        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,        \
@@ -157,6 +165,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
  */
 static void bfa_iocpf_timeout(void *ioc_arg);
 static void bfa_iocpf_sem_timeout(void *ioc_arg);
+static void bfa_iocpf_poll_timeout(void *ioc_arg);
 
 /*
  * IOCPF state machine events
@@ -173,6 +182,7 @@ enum iocpf_event {
        IOCPF_E_GETATTRFAIL     = 9,    /*  init fail notice by ioc sm  */
        IOCPF_E_SEMLOCKED       = 10,   /*  h/w semaphore is locked     */
        IOCPF_E_TIMEOUT         = 11,   /*  f/w response timeout        */
+       IOCPF_E_SEM_ERROR       = 12,   /*  h/w sem mapping error       */
 };
 
 /*
@@ -314,11 +324,16 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
                /* !!! fall through !!! */
        case IOC_E_HWERROR:
                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
                if (event != IOC_E_PFFAILED)
                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
                break;
 
+       case IOC_E_HWFAILED:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+               break;
+
        case IOC_E_DISABLE:
                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
                break;
@@ -356,17 +371,23 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
        case IOC_E_FWRSP_GETATTR:
                bfa_ioc_timer_stop(ioc);
                bfa_ioc_check_attr_wwns(ioc);
+               bfa_ioc_hb_monitor(ioc);
                bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
                break;
 
+       case IOC_E_FWRSP_ACQ_ADDR:
+               bfa_ioc_timer_stop(ioc);
+               bfa_ioc_hb_monitor(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_acq_addr);
                break;
+
        case IOC_E_PFFAILED:
        case IOC_E_HWERROR:
                bfa_ioc_timer_stop(ioc);
                /* !!! fall through !!! */
        case IOC_E_TIMEOUT:
                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
                if (event != IOC_E_PFFAILED)
                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
                break;
@@ -384,6 +405,50 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
        }
 }
 
+/*
+ * Acquiring address from fabric (entry function)
+ */
+static void
+bfa_ioc_sm_acq_addr_entry(struct bfa_ioc_s *ioc)
+{
+}
+
+/*
+ *     Acquiring address from the fabric
+ */
+static void
+bfa_ioc_sm_acq_addr(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_FWRSP_GETATTR:
+               bfa_ioc_check_attr_wwns(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+               break;
+
+       case IOC_E_PFFAILED:
+       case IOC_E_HWERROR:
+               bfa_hb_timer_stop(ioc);
+       case IOC_E_HBFAIL:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+               if (event != IOC_E_PFFAILED)
+                       bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_hb_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+               break;
+
+       case IOC_E_ENABLE:
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
 
 static void
 bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
@@ -391,7 +456,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 
        ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
-       bfa_ioc_hb_monitor(ioc);
+       bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
        BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
 }
 
@@ -414,13 +479,13 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
                bfa_hb_timer_stop(ioc);
                /* !!! fall through !!! */
        case IOC_E_HBFAIL:
-               bfa_ioc_fail_notify(ioc);
-
                if (ioc->iocpf.auto_recover)
                        bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
                else
                        bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 
+               bfa_ioc_fail_notify(ioc);
+
                if (event != IOC_E_PFFAILED)
                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
                break;
@@ -461,6 +526,11 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
                break;
 
+       case IOC_E_HWFAILED:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+               bfa_ioc_disable_comp(ioc);
+               break;
+
        default:
                bfa_sm_fault(ioc, event);
        }
@@ -525,12 +595,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
                 * Initialization retry failed.
                 */
                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
                if (event != IOC_E_PFFAILED)
                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
                break;
 
-       case IOC_E_INITFAILED:
-               bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+       case IOC_E_HWFAILED:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
                break;
 
        case IOC_E_ENABLE:
@@ -590,6 +662,35 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
        }
 }
 
+static void
+bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_trc(ioc, 0);
+}
+
+static void
+bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_ENABLE:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               break;
+
+       case IOC_E_DISABLE:
+               ioc->cbfn->disable_cbfn(ioc->bfa);
+               break;
+
+       case IOC_E_DETACH:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
 /*
  * IOCPF State Machine
  */
@@ -600,7 +701,7 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
 static void
 bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
 {
-       iocpf->retry_count = 0;
+       iocpf->fw_mismatch_notified = BFA_FALSE;
        iocpf->auto_recover = bfa_auto_recover;
 }
 
@@ -633,6 +734,28 @@ bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
 {
+       struct bfi_ioc_image_hdr_s      fwhdr;
+       u32     fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate);
+
+       /* h/w sem init */
+       if (fwstate == BFI_IOC_UNINIT)
+               goto sem_get;
+
+       bfa_ioc_fwver_get(iocpf->ioc, &fwhdr);
+
+       if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+               goto sem_get;
+
+       bfa_trc(iocpf->ioc, fwstate);
+       bfa_trc(iocpf->ioc, fwhdr.exec);
+       writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate);
+
+       /*
+        * Try to lock and then unlock the semaphore.
+        */
+       readl(iocpf->ioc->ioc_regs.ioc_sem_reg);
+       writel(1, iocpf->ioc->ioc_regs.ioc_sem_reg);
+sem_get:
        bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -650,7 +773,6 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
        case IOCPF_E_SEMLOCKED:
                if (bfa_ioc_firmware_lock(ioc)) {
                        if (bfa_ioc_sync_start(ioc)) {
-                               iocpf->retry_count = 0;
                                bfa_ioc_sync_join(ioc);
                                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
                        } else {
@@ -664,6 +786,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
                }
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+               break;
+
        case IOCPF_E_DISABLE:
                bfa_sem_timer_stop(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
@@ -689,10 +816,10 @@ bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
        /*
         * Call only the first time sm enters fwmismatch state.
         */
-       if (iocpf->retry_count == 0)
+       if (iocpf->fw_mismatch_notified == BFA_FALSE)
                bfa_ioc_pf_fwmismatch(iocpf->ioc);
 
-       iocpf->retry_count++;
+       iocpf->fw_mismatch_notified = BFA_TRUE;
        bfa_iocpf_timer_start(iocpf->ioc);
 }
 
@@ -757,6 +884,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
                }
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+               break;
+
        case IOCPF_E_DISABLE:
                bfa_sem_timer_stop(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -770,7 +902,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
 {
-       bfa_iocpf_timer_start(iocpf->ioc);
+       iocpf->poll_time = 0;
        bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
 }
 
@@ -787,20 +919,12 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_FWREADY:
-               bfa_iocpf_timer_stop(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
                break;
 
-       case IOCPF_E_INITFAIL:
-               bfa_iocpf_timer_stop(ioc);
-               /*
-                * !!! fall through !!!
-                */
-
        case IOCPF_E_TIMEOUT:
                writel(1, ioc->ioc_regs.ioc_sem_reg);
-               if (event == IOCPF_E_TIMEOUT)
-                       bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+               bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
                break;
 
@@ -820,6 +944,10 @@ static void
 bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
 {
        bfa_iocpf_timer_start(iocpf->ioc);
+       /*
+        * Enable Interrupts before sending fw IOC ENABLE cmd.
+        */
+       iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
        bfa_ioc_send_enable(iocpf->ioc);
 }
 
@@ -860,10 +988,6 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
                break;
 
-       case IOCPF_E_FWREADY:
-               bfa_ioc_send_enable(ioc);
-               break;
-
        default:
                bfa_sm_fault(ioc, event);
        }
@@ -895,16 +1019,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
                break;
 
-       case IOCPF_E_FWREADY:
-               if (bfa_ioc_is_operational(ioc)) {
-                       bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
-                       bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
-               } else {
-                       bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
-                       bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-               }
-               break;
-
        default:
                bfa_sm_fault(ioc, event);
        }
@@ -929,7 +1043,6 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_FWRSP_DISABLE:
-       case IOCPF_E_FWREADY:
                bfa_iocpf_timer_stop(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
                break;
@@ -976,6 +1089,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+               break;
+
        case IOCPF_E_FAIL:
                break;
 
@@ -990,6 +1108,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
 {
+       bfa_ioc_mbox_flush(iocpf->ioc);
        bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
 }
 
@@ -1002,7 +1121,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_ENABLE:
-               iocpf->retry_count = 0;
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
                break;
 
@@ -1019,6 +1137,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
 {
+       bfa_ioc_debug_save_ftrc(iocpf->ioc);
        bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -1035,20 +1154,15 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
        switch (event) {
        case IOCPF_E_SEMLOCKED:
                bfa_ioc_notify_fail(ioc);
-               bfa_ioc_sync_ack(ioc);
-               iocpf->retry_count++;
-               if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
-                       bfa_ioc_sync_leave(ioc);
-                       writel(1, ioc->ioc_regs.ioc_sem_reg);
-                       bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-               } else {
-                       if (bfa_ioc_sync_complete(ioc))
-                               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-                       else {
-                               writel(1, ioc->ioc_regs.ioc_sem_reg);
-                               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-                       }
-               }
+               bfa_ioc_sync_leave(ioc);
+               writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+               writel(1, ioc->ioc_regs.ioc_sem_reg);
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+               break;
+
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
                break;
 
        case IOCPF_E_DISABLE:
@@ -1073,7 +1187,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
 {
-       bfa_fsm_send_event(iocpf->ioc, IOC_E_INITFAILED);
+       bfa_trc(iocpf->ioc, 0);
 }
 
 /*
@@ -1112,7 +1226,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
        /*
         * Flush any queued up mailbox requests.
         */
-       bfa_ioc_mbox_hbfail(iocpf->ioc);
+       bfa_ioc_mbox_flush(iocpf->ioc);
 
        bfa_ioc_hw_sem_get(iocpf->ioc);
 }
@@ -1126,11 +1240,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
        switch (event) {
        case IOCPF_E_SEMLOCKED:
-               iocpf->retry_count = 0;
                bfa_ioc_sync_ack(ioc);
                bfa_ioc_notify_fail(ioc);
                if (!iocpf->auto_recover) {
                        bfa_ioc_sync_leave(ioc);
+                       writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
                        writel(1, ioc->ioc_regs.ioc_sem_reg);
                        bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
                } else {
@@ -1143,6 +1257,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
                }
                break;
 
+       case IOCPF_E_SEM_ERROR:
+               bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+               bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+               break;
+
        case IOCPF_E_DISABLE:
                bfa_sem_timer_stop(ioc);
                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1159,6 +1278,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
 {
+       bfa_trc(iocpf->ioc, 0);
 }
 
 /*
@@ -1185,23 +1305,28 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
  *  BFA IOC private functions
  */
 
+/*
+ * Notify common modules registered for notification.
+ */
 static void
-bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event)
 {
-       struct list_head                        *qe;
-       struct bfa_ioc_hbfail_notify_s  *notify;
+       struct bfa_ioc_notify_s *notify;
+       struct list_head        *qe;
 
-       ioc->cbfn->disable_cbfn(ioc->bfa);
-
-       /*
-        * Notify common modules registered for notification.
-        */
-       list_for_each(qe, &ioc->hb_notify_q) {
-               notify = (struct bfa_ioc_hbfail_notify_s *) qe;
-               notify->cbfn(notify->cbarg);
+       list_for_each(qe, &ioc->notify_q) {
+               notify = (struct bfa_ioc_notify_s *)qe;
+               notify->cbfn(notify->cbarg, event);
        }
 }
 
+static void
+bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+{
+       ioc->cbfn->disable_cbfn(ioc->bfa);
+       bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
+}
+
 bfa_boolean_t
 bfa_ioc_sem_get(void __iomem *sem_reg)
 {
@@ -1211,16 +1336,15 @@ bfa_ioc_sem_get(void __iomem *sem_reg)
 
        r32 = readl(sem_reg);
 
-       while (r32 && (cnt < BFA_SEM_SPINCNT)) {
+       while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
                cnt++;
                udelay(2);
                r32 = readl(sem_reg);
        }
 
-       if (r32 == 0)
+       if (!(r32 & 1))
                return BFA_TRUE;
 
-       WARN_ON(cnt >= BFA_SEM_SPINCNT);
        return BFA_FALSE;
 }
 
@@ -1234,7 +1358,12 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
         * will return 1. Semaphore is released by writing 1 to the register
         */
        r32 = readl(ioc->ioc_regs.ioc_sem_reg);
-       if (r32 == 0) {
+       if (r32 == ~0) {
+               WARN_ON(r32 == ~0);
+               bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
+               return;
+       }
+       if (!(r32 & 1)) {
                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
                return;
        }
@@ -1343,7 +1472,7 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
        int i;
 
        drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-               bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+               bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
 
        for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
                if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
@@ -1369,7 +1498,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
 
        bfa_ioc_fwver_get(ioc, &fwhdr);
        drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-               bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+               bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
 
        if (fwhdr.signature != drv_fwhdr->signature) {
                bfa_trc(ioc, fwhdr.signature);
@@ -1377,8 +1506,8 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
                return BFA_FALSE;
        }
 
-       if (swab32(fwhdr.param) != boot_env) {
-               bfa_trc(ioc, fwhdr.param);
+       if (swab32(fwhdr.bootenv) != boot_env) {
+               bfa_trc(ioc, fwhdr.bootenv);
                bfa_trc(ioc, boot_env);
                return BFA_FALSE;
        }
@@ -1414,8 +1543,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 
        bfa_trc(ioc, ioc_fwstate);
 
-       boot_type = BFI_BOOT_TYPE_NORMAL;
-       boot_env = BFI_BOOT_LOADER_OS;
+       boot_type = BFI_FWBOOT_TYPE_NORMAL;
+       boot_env = BFI_FWBOOT_ENV_OS;
 
        /*
         * check if firmware is valid
@@ -1425,6 +1554,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 
        if (!fwvalid) {
                bfa_ioc_boot(ioc, boot_type, boot_env);
+               bfa_ioc_poll_fwinit(ioc);
                return;
        }
 
@@ -1433,7 +1563,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
         * just wait for an initialization completion interrupt.
         */
        if (ioc_fwstate == BFI_IOC_INITING) {
-               ioc->cbfn->reset_cbfn(ioc->bfa);
+               bfa_ioc_poll_fwinit(ioc);
                return;
        }
 
@@ -1452,7 +1582,6 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
                 * be flushed. Otherwise MSI-X interrupts are not delivered.
                 */
                bfa_ioc_msgflush(ioc);
-               ioc->cbfn->reset_cbfn(ioc->bfa);
                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
                return;
        }
@@ -1461,6 +1590,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
         * Initialize the h/w for any other states.
         */
        bfa_ioc_boot(ioc, boot_type, boot_env);
+       bfa_ioc_poll_fwinit(ioc);
 }
 
 static void
@@ -1508,7 +1638,7 @@ bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
 
        bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
                    bfa_ioc_portid(ioc));
-       enable_req.ioc_class = ioc->ioc_mc;
+       enable_req.clscode = cpu_to_be16(ioc->clscode);
        do_gettimeofday(&tv);
        enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
        bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
@@ -1572,25 +1702,26 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
        u32 loff = 0;
        u32 chunkno = 0;
        u32 i;
+       u32 asicmode;
 
        /*
         * Initialize LMEM first before code download
         */
        bfa_ioc_lmem_init(ioc);
 
-       bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
-       fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
+       bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
+       fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
 
        pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
        pgoff = PSS_SMEM_PGOFF(loff);
 
        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
 
-       for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+       for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
 
                if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
                        chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
-                       fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+                       fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
                                        BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
                }
 
@@ -1616,11 +1747,15 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
                        ioc->ioc_regs.host_page_num_fn);
 
        /*
-        * Set boot type and boot param at the end.
-       */
-       bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
+        * Set boot type and device mode at the end.
+        */
+       asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
+                               ioc->port0_mode, ioc->port1_mode);
+       bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
+                       swab32(asicmode));
+       bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,
                        swab32(boot_type));
-       bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
+       bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
                        swab32(boot_env));
 }
 
@@ -1636,6 +1771,7 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
        attr->adapter_prop  = be32_to_cpu(attr->adapter_prop);
        attr->card_type     = be32_to_cpu(attr->card_type);
        attr->maxfrsize     = be16_to_cpu(attr->maxfrsize);
+       ioc->fcmode     = (attr->port_mode == BFI_PORT_MODE_FC);
 
        bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
 }
@@ -1690,7 +1826,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
  * Cleanup any pending requests.
  */
 static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)
 {
        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
        struct bfa_mbox_cmd_s           *cmd;
@@ -1752,6 +1888,7 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
        /*
         *  release semaphore.
         */
+       readl(ioc->ioc_regs.ioc_init_sem_reg);
        writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 
        bfa_trc(ioc, pgnum);
@@ -1808,6 +1945,7 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
        /*
         *  release semaphore.
         */
+       readl(ioc->ioc_regs.ioc_init_sem_reg);
        writel(1, ioc->ioc_regs.ioc_init_sem_reg);
        bfa_trc(ioc, pgnum);
        return BFA_STATUS_OK;
@@ -1816,18 +1954,13 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
 static void
 bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
 {
-       struct list_head                *qe;
-       struct bfa_ioc_hbfail_notify_s  *notify;
        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 
        /*
         * Notify driver and common modules registered for notification.
         */
        ioc->cbfn->hbfail_cbfn(ioc->bfa);
-       list_for_each(qe, &ioc->hb_notify_q) {
-               notify = (struct bfa_ioc_hbfail_notify_s *) qe;
-               notify->cbfn(notify->cbarg);
-       }
+       bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
 
        bfa_ioc_debug_save_ftrc(ioc);
 
@@ -1864,6 +1997,7 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
        /*
         *  release semaphore.
         */
+       readl(ioc->ioc_regs.ioc_init_sem_reg);
        writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 
        return BFA_STATUS_OK;
@@ -1876,8 +2010,6 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
 void
 bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
 {
-       void __iomem *rb;
-
        bfa_ioc_stats(ioc, ioc_boots);
 
        if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
@@ -1886,22 +2018,16 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
        /*
         * Initialize IOC state of all functions on a chip reset.
         */
-       rb = ioc->pcidev.pci_bar_kva;
-       if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
-               writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
-               writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
+       if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
+               writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
+               writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
        } else {
-               writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
-               writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
+               writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
+               writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
        }
 
        bfa_ioc_msgflush(ioc);
        bfa_ioc_download_fw(ioc, boot_type, boot_env);
-
-       /*
-        * Enable interrupts just before starting LPU
-        */
-       ioc->cbfn->reset_cbfn(ioc->bfa);
        bfa_ioc_lpu_start(ioc);
 }
 
@@ -1932,13 +2058,17 @@ bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
                (r32 != BFI_IOC_MEMTEST));
 }
 
-void
+bfa_boolean_t
 bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
 {
        __be32  *msgp = mbmsg;
        u32     r32;
        int             i;
 
+       r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+       if ((r32 & 1) == 0)
+               return BFA_FALSE;
+
        /*
         * read the MBOX msg
         */
@@ -1954,6 +2084,8 @@ bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
         */
        writel(1, ioc->ioc_regs.lpu_mbox_cmd);
        readl(ioc->ioc_regs.lpu_mbox_cmd);
+
+       return BFA_TRUE;
 }
 
 void
@@ -1970,11 +2102,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
        case BFI_IOC_I2H_HBEAT:
                break;
 
-       case BFI_IOC_I2H_READY_EVENT:
-               bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
-               break;
-
        case BFI_IOC_I2H_ENABLE_REPLY:
+               ioc->port_mode = ioc->port_mode_cfg =
+                               (enum bfa_mode_s)msg->fw_event.port_mode;
+               ioc->ad_cap_bm = msg->fw_event.cap_bm;
                bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
                break;
 
@@ -1986,6 +2117,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
                bfa_ioc_getattr_reply(ioc);
                break;
 
+       case BFI_IOC_I2H_ACQ_ADDR_REPLY:
+               bfa_fsm_send_event(ioc, IOC_E_FWRSP_ACQ_ADDR);
+               break;
+
        default:
                bfa_trc(ioc, msg->mh.msg_id);
                WARN_ON(1);
@@ -2011,7 +2146,7 @@ bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
        ioc->iocpf.ioc  = ioc;
 
        bfa_ioc_mbox_attach(ioc);
-       INIT_LIST_HEAD(&ioc->hb_notify_q);
+       INIT_LIST_HEAD(&ioc->notify_q);
 
        bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
        bfa_fsm_send_event(ioc, IOC_E_RESET);
@@ -2024,6 +2159,7 @@ void