]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
scsi:lpfc update to 8.3.5.58
authorMaxim Uvarov <maxim.uvarov@oracle.com>
Fri, 6 Jan 2012 21:30:21 +0000 (13:30 -0800)
committerMaxim Uvarov <maxim.uvarov@oracle.com>
Wed, 11 Jan 2012 01:01:36 +0000 (17:01 -0800)
Signed-off-by: Maxim Uvarov <maxim.uvarov@oracle.com>
27 files changed:
drivers/scsi/lpfc/Makefile
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_bsg.h
drivers/scsi/lpfc/lpfc_compat.h
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_debugfs.h
drivers/scsi/lpfc/lpfc_disc.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_logmsg.h
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_mem.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_scsi.h
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli.h
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/lpfc/lpfc_vport.c

index 88928f00aa2db3dc1896f93f1b9c261be77e629d..b8f4055f594ada69f14168484a1bc33272e0d86b 100644 (file)
@@ -1,7 +1,7 @@
 #/*******************************************************************
 # * This file is part of the Emulex Linux Device Driver for         *
 # * Fibre Channel Host Bus Adapters.                                *
-# * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
+# * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
 # * EMULEX and SLI are trademarks of Emulex.                        *
 # * www.emulex.com                                                  *
 # *                                                                 *
 # *******************************************************************/
 ######################################################################
 
-ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage
-ccflags-$(GCOV) += -O0
+ifneq ($(GCOV),)
+  EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage
+  EXTRA_CFLAGS += -O0
+endif
 
 obj-$(CONFIG_SCSI_LPFC) := lpfc.o
 
index 0441361c79c893dd38bb465eaa0ca16328b13ae8..82a0ad94d42e83331c9500800f2081f4df0c6140 100644 (file)
@@ -247,18 +247,6 @@ struct lpfc_stats {
        uint32_t fcpLocalErr;
 };
 
-enum sysfs_mbox_state {
-       SMBOX_IDLE,
-       SMBOX_WRITING,
-       SMBOX_READING
-};
-
-struct lpfc_sysfs_mbox {
-       enum sysfs_mbox_state state;
-       size_t                offset;
-       struct lpfcMboxq *    mbox;
-};
-
 struct lpfc_hba;
 
 
@@ -579,9 +567,9 @@ struct lpfc_hba {
        void (*lpfc_stop_port)
                (struct lpfc_hba *);
        int (*lpfc_hba_init_link)
-               (struct lpfc_hba *, uint32_t);
+               (struct lpfc_hba *);
        int (*lpfc_hba_down_link)
-               (struct lpfc_hba *, uint32_t);
+               (struct lpfc_hba *);
        int (*lpfc_selective_reset)
                (struct lpfc_hba *);
 
@@ -680,6 +668,9 @@ struct lpfc_hba {
        uint32_t cfg_enable_rrq;
        uint32_t cfg_topology;
        uint32_t cfg_link_speed;
+#define LPFC_FCF_FOV 1         /* Fast fcf failover */
+#define LPFC_FCF_PRIORITY 2    /* Priority fcf failover */
+       uint32_t cfg_fcf_failover_policy;
        uint32_t cfg_cr_delay;
        uint32_t cfg_cr_count;
        uint32_t cfg_multi_ring_support;
@@ -780,8 +771,6 @@ struct lpfc_hba {
        uint64_t bg_apptag_err_cnt;
        uint64_t bg_reftag_err_cnt;
 
-       struct lpfc_sysfs_mbox sysfs_mbox;
-
        /* fastpath list. */
        spinlock_t scsi_buf_list_lock;
        struct list_head lpfc_scsi_buf_list;
@@ -843,17 +832,37 @@ struct lpfc_hba {
        struct dentry *debug_hbqinfo;
        struct dentry *debug_dumpHostSlim;
        struct dentry *debug_dumpHBASlim;
-       struct dentry *debug_dumpData;   /* BlockGuard BPL*/
-       struct dentry *debug_dumpDif;    /* BlockGuard BPL*/
+       struct dentry *debug_dumpData;   /* BlockGuard BPL */
+       struct dentry *debug_dumpDif;    /* BlockGuard BPL */
+       struct dentry *debug_InjErrLBA;  /* LBA to inject errors at */
+       struct dentry *debug_writeGuard; /* inject write guard_tag errors */
+       struct dentry *debug_writeApp;   /* inject write app_tag errors */
+       struct dentry *debug_writeRef;   /* inject write ref_tag errors */
+       struct dentry *debug_readApp;    /* inject read app_tag errors */
+       struct dentry *debug_readRef;    /* inject read ref_tag errors */
+
+       /* T10 DIF error injection */
+       uint32_t lpfc_injerr_wgrd_cnt;
+       uint32_t lpfc_injerr_wapp_cnt;
+       uint32_t lpfc_injerr_wref_cnt;
+       uint32_t lpfc_injerr_rapp_cnt;
+       uint32_t lpfc_injerr_rref_cnt;
+       sector_t lpfc_injerr_lba;
+#define LPFC_INJERR_LBA_OFF    (sector_t)0xffffffffffffffff
+
        struct dentry *debug_slow_ring_trc;
        struct lpfc_debugfs_trc *slow_ring_trc;
        atomic_t slow_ring_trc_cnt;
        /* iDiag debugfs sub-directory */
        struct dentry *idiag_root;
        struct dentry *idiag_pci_cfg;
+       struct dentry *idiag_bar_acc;
        struct dentry *idiag_que_info;
        struct dentry *idiag_que_acc;
        struct dentry *idiag_drb_acc;
+       struct dentry *idiag_ctl_acc;
+       struct dentry *idiag_mbx_acc;
+       struct dentry *idiag_ext_acc;
 #endif
 
        /* Used for deferred freeing of ELS data buffers */
index f4c6fa5ef4d03e258ddadfb88e863b8610e5f061..17aaec9420cb558a186b08f866a8d55d4cb9b99c 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/interrupt.h>
 #include <linux/aer.h>
 #include <linux/gfp.h>
-#include <linux/kernel.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #define LPFC_MIN_DEVLOSS_TMO 1
 #define LPFC_MAX_DEVLOSS_TMO 255
 
+/*
+ * Write key size should be multiple of 4. If write key is changed
+ * make sure that library write key is also changed.
+ */
+#define LPFC_REG_WRITE_KEY_SIZE        4
+#define LPFC_REG_WRITE_KEY     "EMLX"
+
 /**
  * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
  * @incr: integer to convert.
@@ -343,10 +349,23 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
        struct Scsi_Host  *shost = class_to_shost(dev);
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_hba   *phba = vport->phba;
+       uint32_t if_type;
+       uint8_t sli_family;
        char fwrev[32];
+       int len;
 
        lpfc_decode_firmware_rev(phba, fwrev, 1);
-       return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
+       if_type = phba->sli4_hba.pc_sli4_params.if_type;
+       sli_family = phba->sli4_hba.pc_sli4_params.sli_family;
+
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               len = snprintf(buf, PAGE_SIZE, "%s, sli-%d\n",
+                              fwrev, phba->sli_rev);
+       else
+               len = snprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n",
+                              fwrev, phba->sli_rev, if_type, sli_family);
+
+       return len;
 }
 
 /**
@@ -479,6 +498,34 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
        return len;
 }
 
+/**
+ * lpfc_sli4_protocol_show - Return the fip mode of the HBA
+ * @dev: class unused variable.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the module description text.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_sli4_protocol_show(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba *phba = vport->phba;
+
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               return snprintf(buf, PAGE_SIZE, "fc\n");
+
+       if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) {
+               if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE)
+                       return snprintf(buf, PAGE_SIZE, "fcoe\n");
+               if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC)
+                       return snprintf(buf, PAGE_SIZE, "fc\n");
+       }
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
 /**
  * lpfc_link_state_store - Transition the link_state on an HBA port
  * @dev: class device that is converted into a Scsi_host.
@@ -503,10 +550,10 @@ lpfc_link_state_store(struct device *dev, struct device_attribute *attr,
 
        if ((strncmp(buf, "up", sizeof("up") - 1) == 0) &&
                        (phba->link_state == LPFC_LINK_DOWN))
-               status = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+               status = phba->lpfc_hba_init_link(phba);
        else if ((strncmp(buf, "down", sizeof("down") - 1) == 0) &&
                        (phba->link_state >= LPFC_LINK_UP))
-               status = phba->lpfc_hba_down_link(phba, MBX_NOWAIT);
+               status = phba->lpfc_hba_down_link(phba);
 
        if (status == 0)
                return strlen(buf);
@@ -693,7 +740,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
        int rc;
 
        if (!phba->cfg_enable_hba_reset)
-               return -EIO;
+               return -EACCES;
 
        status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
 
@@ -742,9 +789,11 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
        struct Scsi_Host  *shost = class_to_shost(dev);
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_hba   *phba = vport->phba;
-
        int status = -EINVAL;
 
+       if (!phba->cfg_enable_hba_reset)
+               return -EACCES;
+
        if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
                status = phba->lpfc_selective_reset(phba);
 
@@ -763,18 +812,28 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
  * the readyness after performing a firmware reset.
  *
  * Returns:
- * zero for success
+ * zero for success, -EPERM when port does not have privilage to perform the
+ * reset, -EIO when port timeout from recovering from the reset.
+ *
+ * Note:
+ * As the caller will interpret the return code by value, be careful in making
+ * change or addition to return codes.
  **/
-static int
+int
 lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
 {
-       struct lpfc_register portstat_reg;
+       struct lpfc_register portstat_reg = {0};
        int i;
 
-
+       msleep(100);
        lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
                   &portstat_reg.word0);
 
+       /* verify if privilaged for the request operation */
+       if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
+           !bf_get(lpfc_sliport_status_err, &portstat_reg))
+               return -EPERM;
+
        /* wait for the SLI port firmware ready after firmware reset */
        for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
                msleep(10);
@@ -810,18 +869,30 @@ static ssize_t
 lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
 {
        struct completion online_compl;
+       struct pci_dev *pdev = phba->pcidev;
+       uint32_t before_fc_flag;
+       uint32_t sriov_nr_virtfn;
        uint32_t reg_val;
-       int status = 0;
-       int rc;
+       int status = 0, rc = 0;
+       int job_posted = 1, sriov_err;
 
        if (!phba->cfg_enable_hba_reset)
-               return -EIO;
+               return -EACCES;
 
        if ((phba->sli_rev < LPFC_SLI_REV4) ||
            (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
             LPFC_SLI_INTF_IF_TYPE_2))
                return -EPERM;
 
+       /* Keep state if we need to restore back */
+       before_fc_flag = phba->pport->fc_flag;
+       sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn;
+
+       /* Disable SR-IOV virtual functions if enabled */
+       if (phba->cfg_sriov_nr_virtfn) {
+               pci_disable_sriov(pdev);
+               phba->cfg_sriov_nr_virtfn = 0;
+       }
        status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
 
        if (status != 0)
@@ -848,21 +919,44 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
        /* delay driver action following IF_TYPE_2 reset */
        rc = lpfc_sli4_pdev_status_reg_wait(phba);
 
-       if (rc)
-               return -EIO;
+       if (rc == -EPERM) {
+               /* no privilage for reset, restore if needed */
+               if (before_fc_flag & FC_OFFLINE_MODE)
+                       goto out;
+       } else if (rc == -EIO) {
+               /* reset failed, there is nothing more we can do */
+               return rc;
+       }
+
+       /* keep the original port state */
+       if (before_fc_flag & FC_OFFLINE_MODE)
+               goto out;
 
        init_completion(&online_compl);
-       rc = lpfc_workq_post_event(phba, &status, &online_compl,
-                                  LPFC_EVT_ONLINE);
-       if (rc == 0)
-               return -ENOMEM;
+       job_posted = lpfc_workq_post_event(phba, &status, &online_compl,
+                                          LPFC_EVT_ONLINE);
+       if (!job_posted)
+               goto out;
 
        wait_for_completion(&online_compl);
 
-       if (status != 0)
-               return -EIO;
+out:
+       /* in any case, restore the virtual functions enabled as before */
+       if (sriov_nr_virtfn) {
+               sriov_err =
+                       lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn);
+               if (!sriov_err)
+                       phba->cfg_sriov_nr_virtfn = sriov_nr_virtfn;
+       }
 
-       return 0;
+       /* return proper error code */
+       if (!rc) {
+               if (!job_posted)
+                       rc = -ENOMEM;
+               else if (status)
+                       rc = -EIO;
+       }
+       return rc;
 }
 
 /**
@@ -934,33 +1028,38 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
        struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_hba   *phba = vport->phba;
        struct completion online_compl;
-       int status=0;
+       char *board_mode_str = NULL;
+       int status = 0;
        int rc;
 
-       if (!phba->cfg_enable_hba_reset)
-               return -EACCES;
+       if (!phba->cfg_enable_hba_reset) {
+               status = -EACCES;
+               goto board_mode_out;
+       }
 
        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-               "3050 lpfc_board_mode set to %s\n", buf);
+                        "3050 lpfc_board_mode set to %s\n", buf);
 
        init_completion(&online_compl);
 
        if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
                rc = lpfc_workq_post_event(phba, &status, &online_compl,
                                      LPFC_EVT_ONLINE);
-               if (rc == 0)
-                       return -ENOMEM;
+               if (rc == 0) {
+                       status = -ENOMEM;
+                       goto board_mode_out;
+               }
                wait_for_completion(&online_compl);
        } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
                status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
        else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
                if (phba->sli_rev == LPFC_SLI_REV4)
-                       return -EINVAL;
+                       status = -EINVAL;
                else
                        status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);
        else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
                if (phba->sli_rev == LPFC_SLI_REV4)
-                       return -EINVAL;
+                       status = -EINVAL;
                else
                        status = lpfc_do_offline(phba, LPFC_EVT_KILL);
        else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0)
@@ -970,12 +1069,21 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
        else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0)
                status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET);
        else
-               return -EINVAL;
+               status = -EINVAL;
 
+board_mode_out:
        if (!status)
                return strlen(buf);
-       else
-               return -EIO;
+       else {
+               board_mode_str = strchr(buf, '\n');
+               if (board_mode_str)
+                       *board_mode_str = '\0';
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                "3097 Failed \"%s\", status(%d), "
+                                "fc_flag(x%x)\n",
+                                buf, status, phba->pport->fc_flag);
+               return status;
+       }
 }
 
 /**
@@ -1921,6 +2029,7 @@ static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL);
 static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL);
 static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO,
                   lpfc_sriov_hw_max_virtfn_show, NULL);
+static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
 
 static char *lpfc_soft_wwn_key = "C99G71SL8032A";
 
@@ -2040,11 +2149,12 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
 
        /* Validate and store the new name */
        for (i=0, j=0; i < 16; i++) {
-               int value;
-
-               value = hex_to_bin(*buf++);
-               if (value >= 0)
-                       j = (j << 4) | value;
+               if ((*buf >= 'a') && (*buf <= 'f'))
+                       j = ((j << 4) | ((*buf++ -'a') + 10));
+               else if ((*buf >= 'A') && (*buf <= 'F'))
+                       j = ((j << 4) | ((*buf++ -'A') + 10));
+               else if ((*buf >= '0') && (*buf <= '9'))
+                       j = ((j << 4) | (*buf++ -'0'));
                else
                        return -EINVAL;
                if (i % 2) {
@@ -2136,11 +2246,12 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
 
        /* Validate and store the new name */
        for (i=0, j=0; i < 16; i++) {
-               int value;
-
-               value = hex_to_bin(*buf++);
-               if (value >= 0)
-                       j = (j << 4) | value;
+               if ((*buf >= 'a') && (*buf <= 'f'))
+                       j = ((j << 4) | ((*buf++ -'a') + 10));
+               else if ((*buf >= 'A') && (*buf <= 'F'))
+                       j = ((j << 4) | ((*buf++ -'A') + 10));
+               else if ((*buf >= '0') && (*buf <= '9'))
+                       j = ((j << 4) | (*buf++ -'0'));
                else
                        return -EINVAL;
                if (i % 2) {
@@ -2184,6 +2295,10 @@ lpfc_param_show(enable_npiv);
 lpfc_param_init(enable_npiv, 1, 0, 1);
 static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
 
+LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2,
+       "FCF Fast failover=1 Priority failover=2");
+
+
 int lpfc_enable_rrq;
 module_param(lpfc_enable_rrq, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
@@ -2374,11 +2489,6 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
        if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
                vport->cfg_nodev_tmo = val;
                vport->cfg_devloss_tmo = val;
-               /*
-                * For compat: set the fc_host dev loss so new rports
-                * will get the value.
-                */
-               fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
                lpfc_update_rport_devloss_tmo(vport);
                return 0;
        }
@@ -2428,7 +2538,6 @@ lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
                vport->cfg_nodev_tmo = val;
                vport->cfg_devloss_tmo = val;
                vport->dev_loss_tmo_changed = 1;
-               fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
                lpfc_update_rport_devloss_tmo(vport);
                return 0;
        }
@@ -2663,6 +2772,14 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
        if (val >= 0 && val <= 6) {
                prev_val = phba->cfg_topology;
                phba->cfg_topology = val;
+               if (phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G &&
+                       val == 4) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                               "3113 Loop mode not supported at speed %d\n",
+                               phba->cfg_link_speed);
+                       phba->cfg_topology = prev_val;
+                       return -EINVAL;
+               }
                if (nolip)
                        return strlen(buf);
 
@@ -3108,6 +3225,14 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
                                val);
                return -EINVAL;
        }
+       if (val == LPFC_USER_LINK_SPEED_16G &&
+                phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3112 lpfc_link_speed attribute cannot be set "
+                               "to %d. Speed is not supported in loop mode.\n",
+                               val);
+               return -EINVAL;
+       }
        if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
            (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
                prev_val = phba->cfg_link_speed;
@@ -3152,6 +3277,13 @@ lpfc_param_show(link_speed)
 static int
 lpfc_link_speed_init(struct lpfc_hba *phba, int val)
 {
+       if (val == LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "3111 lpfc_link_speed of %d cannot "
+                       "support loop mode, setting topology to default.\n",
+                        val);
+               phba->cfg_topology = 0;
+       }
        if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
            (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
                phba->cfg_link_speed = val;
@@ -3662,7 +3794,7 @@ LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat.");
 #       1  = BlockGuard enabled
 # Value range is [0,1]. Default value is 0.
 */
-LPFC_ATTR_R(enable_bg, 1, 0, 1, "Enable BlockGuard Support");
+LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
 
 /*
 # lpfc_prot_mask: i
@@ -3766,6 +3898,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_fdmi_on,
        &dev_attr_lpfc_max_luns,
        &dev_attr_lpfc_enable_npiv,
+       &dev_attr_lpfc_fcf_failover_policy,
        &dev_attr_lpfc_enable_rrq,
        &dev_attr_nport_evt_cnt,
        &dev_attr_board_mode,
@@ -3805,6 +3938,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_fips_rev,
        &dev_attr_lpfc_dss,
        &dev_attr_lpfc_sriov_hw_max_virtfn,
+       &dev_attr_protocol,
        NULL,
 };
 
@@ -3872,18 +4006,23 @@ sysfs_ctlreg_write(struct file *filp, struct kobject *kobj,
        if ((off + count) > FF_REG_AREA_SIZE)
                return -ERANGE;
 
-       if (count == 0) return 0;
+       if (count <= LPFC_REG_WRITE_KEY_SIZE)
+               return 0;
 
        if (off % 4 || count % 4 || (unsigned long)buf % 4)
                return -EINVAL;
 
-       if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
+       /* This is to protect HBA registers from accidental writes. */
+       if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE))
+               return -EINVAL;
+
+       if (!(vport->fc_flag & FC_OFFLINE_MODE))
                return -EPERM;
-       }
 
        spin_lock_irq(&phba->hbalock);
-       for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
-               writel(*((uint32_t *)(buf + buf_off)),
+       for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE;
+                       buf_off += sizeof(uint32_t))
+               writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)),
                       phba->ctrl_regs_memmap_p + off + buf_off);
 
        spin_unlock_irq(&phba->hbalock);
@@ -3957,23 +4096,6 @@ static struct bin_attribute sysfs_ctlreg_attr = {
        .write = sysfs_ctlreg_write,
 };
 
-/**
- * sysfs_mbox_idle - frees the sysfs mailbox
- * @phba: lpfc_hba pointer
- **/
-static void
-sysfs_mbox_idle(struct lpfc_hba *phba)
-{
-       phba->sysfs_mbox.state = SMBOX_IDLE;
-       phba->sysfs_mbox.offset = 0;
-
-       if (phba->sysfs_mbox.mbox) {
-               mempool_free(phba->sysfs_mbox.mbox,
-                            phba->mbox_mem_pool);
-               phba->sysfs_mbox.mbox = NULL;
-       }
-}
-
 /**
  * sysfs_mbox_write - Write method for writing information via mbox
  * @filp: open sysfs file
@@ -3984,71 +4106,18 @@ sysfs_mbox_idle(struct lpfc_hba *phba)
  * @count: bytes to transfer.
  *
  * Description:
- * Accessed via /sys/class/scsi_host/hostxxx/mbox.
- * Uses the sysfs mbox to send buf contents to the adapter.
+ * Deprecated function. All mailbox access from user space is performed via the
+ * bsg interface.
  *
  * Returns:
- * -ERANGE off and count combo out of range
- * -EINVAL off, count or buff address invalid
- * zero if count is zero
- * -EPERM adapter is offline
- * -ENOMEM failed to allocate memory for the mail box
- * -EAGAIN offset, state or mbox is NULL
- * count number of bytes transferred
+ * -EPERM operation not permitted
  **/
 static ssize_t
 sysfs_mbox_write(struct file *filp, struct kobject *kobj,
                 struct bin_attribute *bin_attr,
                 char *buf, loff_t off, size_t count)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct Scsi_Host  *shost = class_to_shost(dev);
-       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-       struct lpfc_hba   *phba = vport->phba;
-       struct lpfcMboxq  *mbox = NULL;
-
-       if ((count + off) > MAILBOX_CMD_SIZE)
-               return -ERANGE;
-
-       if (off % 4 ||  count % 4 || (unsigned long)buf % 4)
-               return -EINVAL;
-
-       if (count == 0)
-               return 0;
-
-       if (off == 0) {
-               mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (!mbox)
-                       return -ENOMEM;
-               memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
-       }
-
-       spin_lock_irq(&phba->hbalock);
-
-       if (off == 0) {
-               if (phba->sysfs_mbox.mbox)
-                       mempool_free(mbox, phba->mbox_mem_pool);
-               else
-                       phba->sysfs_mbox.mbox = mbox;
-               phba->sysfs_mbox.state = SMBOX_WRITING;
-       } else {
-               if (phba->sysfs_mbox.state  != SMBOX_WRITING ||
-                   phba->sysfs_mbox.offset != off           ||
-                   phba->sysfs_mbox.mbox   == NULL) {
-                       sysfs_mbox_idle(phba);
-                       spin_unlock_irq(&phba->hbalock);
-                       return -EAGAIN;
-               }
-       }
-
-       memcpy((uint8_t *) &phba->sysfs_mbox.mbox->u.mb + off,
-              buf, count);
-
-       phba->sysfs_mbox.offset = off + count;
-
-       spin_unlock_irq(&phba->hbalock);
-
-       return count;
+       return -EPERM;
 }
 
 /**
@@ -4061,199 +4130,18 @@ sysfs_mbox_write(struct file *filp, struct kobject *kobj,
  * @count: bytes to transfer.
  *
  * Description:
- * Accessed via /sys/class/scsi_host/hostxxx/mbox.
- * Uses the sysfs mbox to receive data from to the adapter.
+ * Deprecated function. All mailbox access from user space is performed via the
+ * bsg interface.
  *
  * Returns:
- * -ERANGE off greater than mailbox command size
- * -EINVAL off, count or buff address invalid
- * zero if off and count are zero
- * -EACCES adapter over temp
- * -EPERM garbage can value to catch a multitude of errors
- * -EAGAIN management IO not permitted, state or off error
- * -ETIME mailbox timeout
- * -ENODEV mailbox error
- * count number of bytes transferred
+ * -EPERM operation not permitted
  **/
 static ssize_t
 sysfs_mbox_read(struct file *filp, struct kobject *kobj,
                struct bin_attribute *bin_attr,
                char *buf, loff_t off, size_t count)
 {
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct Scsi_Host  *shost = class_to_shost(dev);
-       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-       struct lpfc_hba   *phba = vport->phba;
-       int rc;
-       MAILBOX_t *pmb;
-
-       if (off > MAILBOX_CMD_SIZE)
-               return -ERANGE;
-
-       if ((count + off) > MAILBOX_CMD_SIZE)
-               count = MAILBOX_CMD_SIZE - off;
-
-       if (off % 4 ||  count % 4 || (unsigned long)buf % 4)
-               return -EINVAL;
-
-       if (off && count == 0)
-               return 0;
-
-       spin_lock_irq(&phba->hbalock);
-
-       if (phba->over_temp_state == HBA_OVER_TEMP) {
-               sysfs_mbox_idle(phba);
-               spin_unlock_irq(&phba->hbalock);
-               return  -EACCES;
-       }
-
-       if (off == 0 &&
-           phba->sysfs_mbox.state  == SMBOX_WRITING &&
-           phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) {
-               pmb = &phba->sysfs_mbox.mbox->u.mb;
-               switch (pmb->mbxCommand) {
-                       /* Offline only */
-               case MBX_INIT_LINK:
-               case MBX_DOWN_LINK:
-               case MBX_CONFIG_LINK:
-               case MBX_CONFIG_RING:
-               case MBX_RESET_RING:
-               case MBX_UNREG_LOGIN:
-               case MBX_CLEAR_LA:
-               case MBX_DUMP_CONTEXT:
-               case MBX_RUN_DIAGS:
-               case MBX_RESTART:
-               case MBX_SET_MASK:
-               case MBX_SET_DEBUG:
-                       if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
-                               printk(KERN_WARNING "mbox_read:Command 0x%x "
-                                      "is illegal in on-line state\n",
-                                      pmb->mbxCommand);
-                               sysfs_mbox_idle(phba);
-                               spin_unlock_irq(&phba->hbalock);
-                               return -EPERM;
-                       }
-               case MBX_WRITE_NV:
-               case MBX_WRITE_VPARMS:
-               case MBX_LOAD_SM:
-               case MBX_READ_NV:
-               case MBX_READ_CONFIG:
-               case MBX_READ_RCONFIG:
-               case MBX_READ_STATUS:
-               case MBX_READ_XRI:
-               case MBX_READ_REV:
-               case MBX_READ_LNK_STAT:
-               case MBX_DUMP_MEMORY:
-               case MBX_DOWN_LOAD:
-               case MBX_UPDATE_CFG:
-               case MBX_KILL_BOARD:
-               case MBX_LOAD_AREA:
-               case MBX_LOAD_EXP_ROM:
-               case MBX_BEACON:
-               case MBX_DEL_LD_ENTRY:
-               case MBX_SET_VARIABLE:
-               case MBX_WRITE_WWN:
-               case MBX_PORT_CAPABILITIES:
-               case MBX_PORT_IOV_CONTROL:
-                       break;
-               case MBX_SECURITY_MGMT:
-               case MBX_AUTH_PORT:
-                       if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) {
-                               printk(KERN_WARNING "mbox_read:Command 0x%x "
-                                      "is not permitted\n", pmb->mbxCommand);
-                               sysfs_mbox_idle(phba);
-                               spin_unlock_irq(&phba->hbalock);
-                               return -EPERM;
-                       }
-                       break;
-               case MBX_READ_SPARM64:
-               case MBX_READ_TOPOLOGY:
-               case MBX_REG_LOGIN:
-               case MBX_REG_LOGIN64:
-               case MBX_CONFIG_PORT:
-               case MBX_RUN_BIU_DIAG:
-                       printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
-                              pmb->mbxCommand);
-                       sysfs_mbox_idle(phba);
-                       spin_unlock_irq(&phba->hbalock);
-                       return -EPERM;
-               default:
-                       printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
-                              pmb->mbxCommand);
-                       sysfs_mbox_idle(phba);
-                       spin_unlock_irq(&phba->hbalock);
-                       return -EPERM;
-               }
-
-               /* If HBA encountered an error attention, allow only DUMP
-                * or RESTART mailbox commands until the HBA is restarted.
-                */
-               if (phba->pport->stopped &&
-                   pmb->mbxCommand != MBX_DUMP_MEMORY &&
-                   pmb->mbxCommand != MBX_RESTART &&
-                   pmb->mbxCommand != MBX_WRITE_VPARMS &&
-                   pmb->mbxCommand != MBX_WRITE_WWN)
-                       lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
-                                       "1259 mbox: Issued mailbox cmd "
-                                       "0x%x while in stopped state.\n",
-                                       pmb->mbxCommand);
-
-               phba->sysfs_mbox.mbox->vport = vport;
-
-               /* Don't allow mailbox commands to be sent when blocked
-                * or when in the middle of discovery
-                */
-               if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
-                       sysfs_mbox_idle(phba);
-                       spin_unlock_irq(&phba->hbalock);
-                       return  -EAGAIN;
-               }
-
-               if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-                   (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))) {
-
-                       spin_unlock_irq(&phba->hbalock);
-                       rc = lpfc_sli_issue_mbox (phba,
-                                                 phba->sysfs_mbox.mbox,
-                                                 MBX_POLL);
-                       spin_lock_irq(&phba->hbalock);
-
-               } else {
-                       spin_unlock_irq(&phba->hbalock);
-                       rc = lpfc_sli_issue_mbox_wait (phba,
-                                                      phba->sysfs_mbox.mbox,
-                               lpfc_mbox_tmo_val(phba, pmb->mbxCommand) * HZ);
-                       spin_lock_irq(&phba->hbalock);
-               }
-
-               if (rc != MBX_SUCCESS) {
-                       if (rc == MBX_TIMEOUT) {
-                               phba->sysfs_mbox.mbox = NULL;
-                       }
-                       sysfs_mbox_idle(phba);
-                       spin_unlock_irq(&phba->hbalock);
-                       return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
-               }
-               phba->sysfs_mbox.state = SMBOX_READING;
-       }
-       else if (phba->sysfs_mbox.offset != off ||
-                phba->sysfs_mbox.state  != SMBOX_READING) {
-               printk(KERN_WARNING  "mbox_read: Bad State\n");
-               sysfs_mbox_idle(phba);
-               spin_unlock_irq(&phba->hbalock);
-               return -EAGAIN;
-       }
-
-       memcpy(buf, (uint8_t *) &pmb + off, count);
-
-       phba->sysfs_mbox.offset = off + count;
-
-       if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
-               sysfs_mbox_idle(phba);
-
-       spin_unlock_irq(&phba->hbalock);
-
-       return count;
+       return -EPERM;
 }
 
 static struct bin_attribute sysfs_mbox_attr = {
@@ -4397,8 +4285,13 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
                case LPFC_LINK_UP:
                case LPFC_CLEAR_LA:
                case LPFC_HBA_READY:
-                       /* Links up, beyond this port_type reports state */
-                       fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+                       /* Links up, reports port state accordingly */
+                       if (vport->port_state < LPFC_VPORT_READY)
+                               fc_host_port_state(shost) =
+                                                       FC_PORTSTATE_BYPASSED;
+                       else
+                               fc_host_port_state(shost) =
+                                                       FC_PORTSTATE_ONLINE;
                        break;
                case LPFC_HBA_ERROR:
                        fc_host_port_state(shost) = FC_PORTSTATE_ERROR;
@@ -4467,9 +4360,10 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
 
        spin_lock_irq(shost->host_lock);
 
-       if ((vport->fc_flag & FC_FABRIC) ||
-           ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
-            (vport->fc_flag & FC_PUBLIC_LOOP)))
+       if ((vport->port_state > LPFC_FLOGI) &&
+           ((vport->fc_flag & FC_FABRIC) ||
+            ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
+             (vport->fc_flag & FC_PUBLIC_LOOP))))
                node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
        else
                /* fabric is local port if there is no F/FL_Port */
@@ -4542,9 +4436,17 @@ lpfc_get_stats(struct Scsi_Host *shost)
        memset(hs, 0, sizeof (struct fc_host_statistics));
 
        hs->tx_frames = pmb->un.varRdStatus.xmitFrameCnt;
-       hs->tx_words = (pmb->un.varRdStatus.xmitByteCnt * 256);
+       /*
+        * The MBX_READ_STATUS returns tx_k_bytes which has to
+        * converted to words
+        */
+       hs->tx_words = (uint64_t)
+                       ((uint64_t)pmb->un.varRdStatus.xmitByteCnt
+                       * (uint64_t)256);
        hs->rx_frames = pmb->un.varRdStatus.rcvFrameCnt;
-       hs->rx_words = (pmb->un.varRdStatus.rcvByteCnt * 256);
+       hs->rx_words = (uint64_t)
+                       ((uint64_t)pmb->un.varRdStatus.rcvByteCnt
+                        * (uint64_t)256);
 
        memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
        pmb->mbxCommand = MBX_READ_LNK_STAT;
@@ -4986,6 +4888,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        lpfc_link_speed_init(phba, lpfc_link_speed);
        lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
        lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
+       lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy);
        lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
        lpfc_use_msi_init(phba, lpfc_use_msi);
        lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
index f46378fb802ca32429c15623beb40a63a2fcae81..d3ebe4060dac64309940c112a5fbad1d939ff0df 100644 (file)
@@ -42,6 +42,7 @@
 #include "lpfc.h"
 #include "lpfc_logmsg.h"
 #include "lpfc_crtn.h"
+#include "lpfc_debugfs.h"
 #include "lpfc_vport.h"
 #include "lpfc_version.h"
 
@@ -140,6 +141,7 @@ struct lpfc_dmabufext {
        uint32_t flag;
 };
 
+
 /**
  * lpfc_bsg_send_mgmt_cmd_cmp - lpfc_bsg_send_mgmt_cmd's completion handler
  * @phba: Pointer to HBA context object.
@@ -915,9 +917,11 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                                } else {
                                        switch (cmd) {
                                        case ELX_LOOPBACK_DATA:
-                                               diag_cmd_data_free(phba,
-                                               (struct lpfc_dmabufext *)
-                                                       dmabuf);
+                                               if (phba->sli_rev <
+                                                   LPFC_SLI_REV4)
+                                                       diag_cmd_data_free(phba,
+                                                       (struct lpfc_dmabufext
+                                                        *)dmabuf);
                                                break;
                                        case ELX_LOOPBACK_XRI_SETUP:
                                                if ((phba->sli_rev ==
@@ -999,7 +1003,8 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 error_ct_unsol_exit:
        if (!list_empty(&head))
                list_del(&head);
-       if (evt_req_id == SLI_CT_ELX_LOOPBACK)
+       if ((phba->sli_rev < LPFC_SLI_REV4) &&
+           (evt_req_id == SLI_CT_ELX_LOOPBACK))
                return 0;
        return 1;
 }
@@ -1393,6 +1398,7 @@ no_dd_data:
        return rc;
 }
 
+
 /**
  * lpfc_bsg_send_mgmt_rsp - process a SEND_MGMT_RESP bsg vendor command
  * @job: SEND_MGMT_RESP fc_bsg_job
@@ -1565,8 +1571,8 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
        struct diag_mode_set *loopback_mode;
        uint32_t link_flags;
        uint32_t timeout;
-       LPFC_MBOXQ_t *pmboxq;
-       int mbxstatus;
+       LPFC_MBOXQ_t *pmboxq  = NULL;
+       int mbxstatus = MBX_SUCCESS;
        int i = 0;
        int rc = 0;
 
@@ -1614,7 +1620,6 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
                                rc = -ETIMEDOUT;
                                goto loopback_mode_exit;
                        }
-
                        msleep(10);
                }
 
@@ -1634,7 +1639,9 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
                if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus))
                        rc = -ENODEV;
                else {
+                       spin_lock_irq(&phba->hbalock);
                        phba->link_flag |= LS_LOOPBACK_MODE;
+                       spin_unlock_irq(&phba->hbalock);
                        /* wait for the link attention interrupt */
                        msleep(100);
 
@@ -1658,7 +1665,7 @@ loopback_mode_exit:
        /*
         * Let SLI layer release mboxq if mbox command completed after timeout.
         */
-       if (mbxstatus != MBX_TIMEOUT)
+       if (pmboxq && mbxstatus != MBX_TIMEOUT)
                mempool_free(pmboxq, phba->mbox_mem_pool);
 
 job_error:
@@ -1699,6 +1706,11 @@ lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag)
                rc = -ENOMEM;
                goto link_diag_state_set_out;
        }
+       lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                       "3128 Set link to diagnostic state:x%x (x%x/x%x)\n",
+                       diag, phba->sli4_hba.link_state.type,
+                       phba->sli4_hba.link_state.number);
+
        link_diag_state = &pmboxq->u.mqe.un.link_diag_state;
        bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req,
               phba->sli4_hba.link_state.number);
@@ -1725,6 +1737,79 @@ link_diag_state_set_out:
        return rc;
 }
 
+/**
+ * lpfc_sli4_bsg_set_internal_loopback - set sli4 internal loopback diagnostic
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is responsible for issuing a sli4 mailbox command for setting
+ * up internal loopback diagnostic.
+ */
+static int
+lpfc_sli4_bsg_set_internal_loopback(struct lpfc_hba *phba)
+{
+       LPFC_MBOXQ_t *pmboxq;
+       uint32_t req_len, alloc_len;
+       struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;
+       int mbxstatus = MBX_SUCCESS, rc = 0;
+
+       pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmboxq)
+               return -ENOMEM;
+       req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) -
+                  sizeof(struct lpfc_sli4_cfg_mhdr));
+       alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
+                               LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK,
+                               req_len, LPFC_SLI4_MBX_EMBED);
+       if (alloc_len != req_len) {
+               mempool_free(pmboxq, phba->mbox_mem_pool);
+               return -ENOMEM;
+       }
+       link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback;
+       bf_set(lpfc_mbx_set_diag_state_link_num,
+              &link_diag_loopback->u.req, phba->sli4_hba.link_state.number);
+       bf_set(lpfc_mbx_set_diag_state_link_type,
+              &link_diag_loopback->u.req, phba->sli4_hba.link_state.type);
+       bf_set(lpfc_mbx_set_diag_lpbk_type, &link_diag_loopback->u.req,
+              LPFC_DIAG_LOOPBACK_TYPE_SERDES);
+
+       mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
+       if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+                               "3127 Failed setup loopback mode mailbox "
+                               "command, rc:x%x, status:x%x\n", mbxstatus,
+                               pmboxq->u.mb.mbxStatus);
+               rc = -ENODEV;
+       }
+       if (pmboxq && (mbxstatus != MBX_TIMEOUT))
+               mempool_free(pmboxq, phba->mbox_mem_pool);
+       return rc;
+}
+
+/**
+ * lpfc_sli4_diag_fcport_reg_setup - setup port registrations for diagnostic
+ * @phba: Pointer to HBA context object.
+ *
+ * This function set up SLI4 FC port registrations for diagnostic run, which
+ * includes all the rpis, vfi, and also vpi.
+ */
+static int
+lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba)
+{
+       int rc;
+
+       if (phba->pport->fc_flag & FC_VFI_REGISTERED) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+                               "3136 Port still had vfi registered: "
+                               "mydid:x%x, fcfi:%d, vfi:%d, vpi:%d\n",
+                               phba->pport->fc_myDID, phba->fcf.fcfi,
+                               phba->sli4_hba.vfi_ids[phba->pport->vfi],
+                               phba->vpi_ids[phba->pport->vpi]);
+               return -EINVAL;
+       }
+       rc = lpfc_issue_reg_vfi(phba->pport);
+       return rc;
+}
+
 /**
  * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command
  * @phba: Pointer to HBA context object.
@@ -1737,10 +1822,8 @@ static int
 lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
 {
        struct diag_mode_set *loopback_mode;
-       uint32_t link_flags, timeout, req_len, alloc_len;
-       struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback;
-       LPFC_MBOXQ_t *pmboxq = NULL;
-       int mbxstatus, i, rc = 0;
+       uint32_t link_flags, timeout;
+       int i, rc = 0;
 
        /* no data to return just the return code */
        job->reply->reply_payload_rcv_len = 0;
@@ -1761,65 +1844,99 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
        if (rc)
                goto job_error;
 
+       /* indicate we are in loobpack diagnostic mode */
+       spin_lock_irq(&phba->hbalock);
+       phba->link_flag |= LS_LOOPBACK_MODE;
+       spin_unlock_irq(&phba->hbalock);
+
+       /* reset port to start frome scratch */
+       rc = lpfc_selective_reset(phba);
+       if (rc)
+               goto job_error;
+
        /* bring the link to diagnostic mode */
+       lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                       "3129 Bring link to diagnostic state.\n");
        loopback_mode = (struct diag_mode_set *)
                job->request->rqst_data.h_vendor.vendor_cmd;
        link_flags = loopback_mode->type;
        timeout = loopback_mode->timeout * 100;
 
        rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1);
-       if (rc)
+       if (rc) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+                               "3130 Failed to bring link to diagnostic "
+                               "state, rc:x%x\n", rc);
                goto loopback_mode_exit;
+       }
 
        /* wait for link down before proceeding */
        i = 0;
        while (phba->link_state != LPFC_LINK_DOWN) {
                if (i++ > timeout) {
                        rc = -ETIMEDOUT;
+                       lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                                       "3131 Timeout waiting for link to "
+                                       "diagnostic mode, timeout:%d ms\n",
+                                       timeout * 10);
                        goto loopback_mode_exit;
                }
                msleep(10);
        }
+
        /* set up loopback mode */
-       pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!pmboxq) {
-               rc = -ENOMEM;
-               goto loopback_mode_exit;
-       }
-       req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) -
-                  sizeof(struct lpfc_sli4_cfg_mhdr));
-       alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
-                               LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK,
-                               req_len, LPFC_SLI4_MBX_EMBED);
-       if (alloc_len != req_len) {
-               rc = -ENOMEM;
+       lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                       "3132 Set up loopback mode:x%x\n", link_flags);
+
+       if (link_flags == INTERNAL_LOOP_BACK)
+               rc = lpfc_sli4_bsg_set_internal_loopback(phba);
+       else if (link_flags == EXTERNAL_LOOP_BACK)
+               rc = lpfc_hba_init_link_fc_topology(phba,
+                                                   FLAGS_TOPOLOGY_MODE_PT_PT);
+       else {
+               rc = -EINVAL;
+               lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
+                               "3141 Loopback mode:x%x not supported\n",
+                               link_flags);
                goto loopback_mode_exit;
        }
-       link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback;
-       bf_set(lpfc_mbx_set_diag_state_link_num,
-              &link_diag_loopback->u.req, phba->sli4_hba.link_state.number);
-       bf_set(lpfc_mbx_set_diag_state_link_type,
-              &link_diag_loopback->u.req, phba->sli4_hba.link_state.type);
-       if (link_flags == INTERNAL_LOOP_BACK)
-               bf_set(lpfc_mbx_set_diag_lpbk_type,
-                      &link_diag_loopback->u.req,
-                      LPFC_DIAG_LOOPBACK_TYPE_INTERNAL);
-       else
-               bf_set(lpfc_mbx_set_diag_lpbk_type,
-                      &link_diag_loopback->u.req,
-                      LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL);
 
-       mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO);
-       if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus))
-               rc = -ENODEV;
-       else {
-               phba->link_flag |= LS_LOOPBACK_MODE;
+       if (!rc) {
                /* wait for the link attention interrupt */
                msleep(100);
                i = 0;
+               while (phba->link_state < LPFC_LINK_UP) {
+                       if (i++ > timeout) {
+                               rc = -ETIMEDOUT;
+                               lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                                       "3137 Timeout waiting for link up "
+                                       "in loopback mode, timeout:%d ms\n",
+                                       timeout * 10);
+                               break;
+                       }
+                       msleep(10);
+               }
+       }
+
+       /* port resource registration setup for loopback diagnostic */
+       if (!rc) {
+               /* set up a none zero myDID for loopback test */
+               phba->pport->fc_myDID = 1;
+               rc = lpfc_sli4_diag_fcport_reg_setup(phba);
+       } else
+               goto loopback_mode_exit;
+
+       if (!rc) {
+               /* wait for the port ready */
+               msleep(100);
+               i = 0;
                while (phba->link_state != LPFC_HBA_READY) {
                        if (i++ > timeout) {
                                rc = -ETIMEDOUT;
+                               lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                                       "3133 Timeout waiting for port "
+                                       "loopback mode ready, timeout:%d ms\n",
+                                       timeout * 10);
                                break;
                        }
                        msleep(10);
@@ -1827,14 +1944,14 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job)
        }
 
 loopback_mode_exit:
+       /* clear loopback diagnostic mode */
+       if (rc) {
+               spin_lock_irq(&phba->hbalock);
+               phba->link_flag &= ~LS_LOOPBACK_MODE;
+               spin_unlock_irq(&phba->hbalock);
+       }
        lpfc_bsg_diag_mode_exit(phba);
 
-       /*
-        * Let SLI layer release mboxq if mbox command completed after timeout.
-        */
-       if (pmboxq && (mbxstatus != MBX_TIMEOUT))
-               mempool_free(pmboxq, phba->mbox_mem_pool);
-
 job_error:
        /* make error code available to userspace */
        job->reply->result = rc;
@@ -1878,7 +1995,6 @@ lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job)
                rc = -ENODEV;
 
        return rc;
-
 }
 
 /**
@@ -1894,7 +2010,9 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job)
        struct Scsi_Host *shost;
        struct lpfc_vport *vport;
        struct lpfc_hba *phba;
-       int rc;
+       struct diag_mode_set *loopback_mode_end_cmd;
+       uint32_t timeout;
+       int rc, i;
 
        shost = job->shost;
        if (!shost)
@@ -1912,11 +2030,47 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job)
            LPFC_SLI_INTF_IF_TYPE_2)
                return -ENODEV;
 
+       /* clear loopback diagnostic mode */
+       spin_lock_irq(&phba->hbalock);
+       phba->link_flag &= ~LS_LOOPBACK_MODE;
+       spin_unlock_irq(&phba->hbalock);
+       loopback_mode_end_cmd = (struct diag_mode_set *)
+                       job->request->rqst_data.h_vendor.vendor_cmd;
+       timeout = loopback_mode_end_cmd->timeout * 100;
+
        rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
+       if (rc) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+                               "3139 Failed to bring link to diagnostic "
+                               "state, rc:x%x\n", rc);
+               goto loopback_mode_end_exit;
+       }
+
+       /* wait for link down before proceeding */
+       i = 0;
+       while (phba->link_state != LPFC_LINK_DOWN) {
+               if (i++ > timeout) {
+                       rc = -ETIMEDOUT;
+                       lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                                       "3140 Timeout waiting for link to "
+                                       "diagnostic mode_end, timeout:%d ms\n",
+                                       timeout * 10);
+                       /* there is nothing much we can do here */
+                       break;
+               }
+               msleep(10);
+       }
 
-       if (!rc)
-               rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+       /* reset port resource registrations */
+       rc = lpfc_selective_reset(phba);
+       phba->pport->fc_myDID = 0;
 
+loopback_mode_end_exit:
+       /* make return code available to userspace */
+       job->reply->result = rc;
+       /* complete the job back to userspace if no error */
+       if (rc == 0)
+               job->job_done(job);
        return rc;
 }
 
@@ -2090,10 +2244,18 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi)
        if (!mbox)
                return -ENOMEM;
 
-       if (phba->sli_rev == LPFC_SLI_REV4)
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
+                               (uint8_t *)&phba->pport->fc_sparam,
+                               mbox, *rpi);
+       else {
                *rpi = lpfc_sli4_alloc_rpi(phba);
-       status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
-                             (uint8_t *)&phba->pport->fc_sparam, mbox, *rpi);
+               status = lpfc_reg_rpi(phba, phba->pport->vpi,
+                               phba->pport->fc_myDID,
+                               (uint8_t *)&phba->pport->fc_sparam,
+                               mbox, *rpi);
+       }
+
        if (status) {
                mempool_free(mbox, phba->mbox_mem_pool);
                if (phba->sli_rev == LPFC_SLI_REV4)
@@ -2116,7 +2278,8 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi)
                return -ENODEV;
        }
 
-       *rpi = mbox->u.mb.un.varWords[0];
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               *rpi = mbox->u.mb.un.varWords[0];
 
        lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys);
        kfree(dmabuff);
@@ -2141,7 +2304,12 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi)
        if (mbox == NULL)
                return -ENOMEM;
 
-       lpfc_unreg_login(phba, 0, rpi, mbox);
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               lpfc_unreg_login(phba, 0, rpi, mbox);
+       else
+               lpfc_unreg_login(phba, phba->pport->vpi,
+                                phba->sli4_hba.rpi_ids[rpi], mbox);
+
        status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
 
        if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
@@ -2629,8 +2797,8 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
        uint32_t full_size;
        size_t segment_len = 0, segment_offset = 0, current_offset = 0;
        uint16_t rpi = 0;
-       struct lpfc_iocbq *cmdiocbq, *rspiocbq;
-       IOCB_t *cmd, *rsp;
+       struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL;
+       IOCB_t *cmd, *rsp = NULL;
        struct lpfc_sli_ct_request *ctreq;
        struct lpfc_dmabuf *txbmp;
        struct ulp_bde64 *txbpl = NULL;
@@ -2664,7 +2832,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
                rc = -EINVAL;
                goto loopback_test_exit;
        }
-
        diag_mode = (struct diag_mode_test *)
                job->request->rqst_data.h_vendor.vendor_cmd;
 
@@ -2719,18 +2886,19 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
        if (rc)
                goto loopback_test_exit;
 
-       rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri);
-       if (rc) {
-               lpfcdiag_loop_self_unreg(phba, rpi);
-               goto loopback_test_exit;
-       }
+       if (phba->sli_rev < LPFC_SLI_REV4) {
+               rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri);
+               if (rc) {
+                       lpfcdiag_loop_self_unreg(phba, rpi);
+                       goto loopback_test_exit;
+               }
 
-       rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
-       if (rc) {
-               lpfcdiag_loop_self_unreg(phba, rpi);
-               goto loopback_test_exit;
+               rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
+               if (rc) {
+                       lpfcdiag_loop_self_unreg(phba, rpi);
+                       goto loopback_test_exit;
+               }
        }
-
        evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,
                                SLI_CT_ELX_LOOPBACK);
        if (!evt) {
@@ -2745,7 +2913,8 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
        spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
        cmdiocbq = lpfc_sli_get_iocbq(phba);
-       rspiocbq = lpfc_sli_get_iocbq(phba);
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               rspiocbq = lpfc_sli_get_iocbq(phba);
        txbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
 
        if (txbmp) {
@@ -2758,14 +2927,18 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
                }
        }
 
-       if (!cmdiocbq || !rspiocbq || !txbmp || !txbpl || !txbuffer ||
-               !txbmp->virt) {
+       if (!cmdiocbq || !txbmp || !txbpl || !txbuffer || !txbmp->virt) {
+               rc = -ENOMEM;
+               goto err_loopback_test_exit;
+       }
+       if ((phba->sli_rev < LPFC_SLI_REV4) && !rspiocbq) {
                rc = -ENOMEM;
                goto err_loopback_test_exit;
        }
 
        cmd = &cmdiocbq->iocb;
-       rsp = &rspiocbq->iocb;
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               rsp = &rspiocbq->iocb;
 
        INIT_LIST_HEAD(&head);
        list_add_tail(&head, &txbuffer->dma.list);
@@ -2795,7 +2968,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
        list_del(&head);
 
        /* Build the XMIT_SEQUENCE iocb */
-
        num_bde = (uint32_t)txbuffer->flag;
 
        cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys);
@@ -2812,16 +2984,27 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
        cmd->ulpBdeCount = 1;
        cmd->ulpLe = 1;
        cmd->ulpClass = CLASS3;
-       cmd->ulpContext = txxri;
 
+       if (phba->sli_rev < LPFC_SLI_REV4) {
+               cmd->ulpContext = txxri;
+       } else {
+               cmd->un.xseq64.bdl.ulpIoTag32 = 0;
+               cmd->un.ulpWord[3] = phba->sli4_hba.rpi_ids[rpi];
+               cmdiocbq->context3 = txbmp;
+               cmdiocbq->sli4_xritag = NO_XRI;
+               cmd->unsli3.rcvsli3.ox_id = 0xffff;
+       }
        cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
        cmdiocbq->vport = phba->pport;
-
        iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
                                             rspiocbq, (phba->fc_ratov * 2) +
                                             LPFC_DRVR_TIMEOUT);
 
-       if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) {
+       if ((iocb_stat != IOCB_SUCCESS) || ((phba->sli_rev < LPFC_SLI_REV4) &&
+                                          (rsp->ulpStatus != IOCB_SUCCESS))) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
+                               "3126 Failed loopback test issue iocb: "
+                               "iocb_stat:x%x\n", iocb_stat);
                rc = -EIO;
                goto err_loopback_test_exit;
        }
@@ -2831,9 +3014,12 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
                evt->wq, !list_empty(&evt->events_to_see),
                ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
        evt->waiting = 0;
-       if (list_empty(&evt->events_to_see))
+       if (list_empty(&evt->events_to_see)) {
                rc = (time_left) ? -EINTR : -ETIMEDOUT;
-       else {
+               lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
+                               "3125 Not receiving unsolicited event, "
+                               "rc:x%x\n", rc);
+       } else {
                spin_lock_irqsave(&phba->ct_ev_lock, flags);
                list_move(evt->events_to_see.prev, &evt->events_to_get);
                evdat = list_entry(evt->events_to_get.prev,
@@ -2890,7 +3076,7 @@ loopback_test_exit:
        job->reply->result = rc;
        job->dd_data = NULL;
        /* complete the job back to userspace if no error */
-       if (rc == 0)
+       if (rc == IOCB_SUCCESS)
                job->job_done(job);
        return rc;
 }
@@ -3077,7 +3263,9 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,
                        && (mb->un.varWords[1] == 1)) {
                        phba->wait_4_mlo_maint_flg = 1;
                } else if (mb->un.varWords[0] == SETVAR_MLORST) {
+                       spin_lock_irq(&phba->hbalock);
                        phba->link_flag &= ~LS_LOOPBACK_MODE;
+                       spin_unlock_irq(&phba->hbalock);
                        phba->fc_topology = LPFC_TOPOLOGY_PT_PT;
                }
                break;
@@ -3139,6 +3327,9 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
        unsigned long flags;
        uint32_t size;
        int rc = 0;
+       struct lpfc_dmabuf *dmabuf;
+       struct lpfc_sli_config_mbox *sli_cfg_mbx;
+       uint8_t *pmbx;
 
        spin_lock_irqsave(&phba->ct_ev_lock, flags);
        dd_data = pmboxq->context1;
@@ -3155,7 +3346,19 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
         */
        pmb = (uint8_t *)&pmboxq->u.mb;
        pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb;
+       /* Copy the byte swapped response mailbox back to the user */
        memcpy(pmb_buf, pmb, sizeof(MAILBOX_t));
+       /* if there is any non-embedded extended data copy that too */
+       dmabuf = phba->mbox_ext_buf_ctx.mbx_dmabuf;
+       sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
+       if (!bsg_bf_get(lpfc_mbox_hdr_emb,
+           &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) {
+               pmbx = (uint8_t *)dmabuf->virt;
+               /* byte swap the extended data following the mailbox command */
+               lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)],
+                       &pmbx[sizeof(MAILBOX_t)],
+                       sli_cfg_mbx->un.sli_config_emb0_subsys.mse[0].buf_len);
+       }
 
        job = dd_data->context_un.mbox.set_job;
        if (job) {
@@ -3177,6 +3380,11 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
                                "(x%x/x%x) complete bsg job done, bsize:%d\n",
                                phba->mbox_ext_buf_ctx.nembType,
                                phba->mbox_ext_buf_ctx.mboxType, size);
+               lpfc_idiag_mbxacc_dump_bsg_mbox(phba,
+                                       phba->mbox_ext_buf_ctx.nembType,
+                                       phba->mbox_ext_buf_ctx.mboxType,
+                                       dma_ebuf, sta_pos_addr,
+                                       phba->mbox_ext_buf_ctx.mbx_dmabuf, 0);
        } else
                spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
 
@@ -3429,6 +3637,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                "ext_buf_cnt:%d\n", ext_buf_cnt);
        }
 
+       /* before dma descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
+                                       sta_pre_addr, dmabuf, ext_buf_cnt);
+
        /* reject non-embedded mailbox command with none external buffer */
        if (ext_buf_cnt == 0) {
                rc = -EPERM;
@@ -3476,6 +3688,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                }
        }
 
+       /* after dma descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox,
+                                       sta_pos_addr, dmabuf, ext_buf_cnt);
+
        /* construct base driver mbox command */
        pmb = &pmboxq->u.mb;
        pmbx = (uint8_t *)dmabuf->virt;
@@ -3505,6 +3721,18 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
        /* state change */
        phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT;
 
+       /*
+        * Non-embedded mailbox subcommand data gets byte swapped here because
+        * the lower level driver code only does the first 64 mailbox words.
+        */
+       if ((!bsg_bf_get(lpfc_mbox_hdr_emb,
+           &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) &&
+               (nemb_tp == nemb_mse))
+               lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)],
+                       &pmbx[sizeof(MAILBOX_t)],
+                               sli_cfg_mbx->un.sli_config_emb0_subsys.
+                                       mse[0].buf_len);
+
        rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
        if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
                lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
@@ -3561,7 +3789,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                        &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr);
                if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
-                                       "2953 Handled SLI_CONFIG(mse) wr, "
+                                       "2953 Failed SLI_CONFIG(mse) wr, "
                                        "ext_buf_cnt(%d) out of range(%d)\n",
                                        ext_buf_cnt,
                                        LPFC_MBX_SLI_CONFIG_MAX_MSE);
@@ -3579,7 +3807,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count;
                if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
-                                       "2954 Handled SLI_CONFIG(hbd) wr, "
+                                       "2954 Failed SLI_CONFIG(hbd) wr, "
                                        "ext_buf_cnt(%d) out of range(%d)\n",
                                        ext_buf_cnt,
                                        LPFC_MBX_SLI_CONFIG_MAX_HBD);
@@ -3590,12 +3818,20 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                "ext_buf_cnt:%d\n", ext_buf_cnt);
        }
 
+       /* before dma buffer descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
+                                       sta_pre_addr, dmabuf, ext_buf_cnt);
+
        if (ext_buf_cnt == 0)
                return -EPERM;
 
        /* for the first external buffer */
        lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf);
 
+       /* after dma descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox,
+                                       sta_pos_addr, dmabuf, ext_buf_cnt);
+
        /* log for looking forward */
        for (i = 1; i < ext_buf_cnt; i++) {
                if (nemb_tp == nemb_mse)
@@ -3665,6 +3901,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                "2956 Failed to issue SLI_CONFIG ext-buffer "
                                "maibox command, rc:x%x\n", rc);
                rc = -EPIPE;
+               goto job_error;
        }
 
        /* wait for additoinal external buffers */
@@ -3699,7 +3936,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
        uint32_t opcode;
        int rc = SLI_CONFIG_NOT_HANDLED;
 
-       /* state change */
+       /* state change on new multi-buffer pass-through mailbox command */
        phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_HOST;
 
        sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt;
@@ -3730,18 +3967,36 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                break;
                        default:
                                lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
-                                               "2959 Not handled SLI_CONFIG "
+                                               "2959 Reject SLI_CONFIG "
                                                "subsys_fcoe, opcode:x%x\n",
                                                opcode);
-                               rc = SLI_CONFIG_NOT_HANDLED;
+                               rc = -EPERM;
+                               break;
+                       }
+               } else if (subsys == SLI_CONFIG_SUBSYS_COMN) {
+                       switch (opcode) {
+                       case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:
+                               lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                                               "3106 Handled SLI_CONFIG "
+                                               "subsys_comn, opcode:x%x\n",
+                                               opcode);
+                               rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job,
+                                                       nemb_mse, dmabuf);
+                               break;
+                       default:
+                               lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
+                                               "3107 Reject SLI_CONFIG "
+                                               "subsys_comn, opcode:x%x\n",
+                                               opcode);
+                               rc = -EPERM;
                                break;
                        }
                } else {
                        lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
-                                       "2977 Handled SLI_CONFIG "
+                                       "2977 Reject SLI_CONFIG "
                                        "subsys:x%d, opcode:x%x\n",
                                        subsys, opcode);
-                       rc = SLI_CONFIG_NOT_HANDLED;
+                       rc = -EPERM;
                }
        } else {
                subsys = bsg_bf_get(lpfc_emb1_subcmnd_subsys,
@@ -3777,12 +4032,17 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
                        }
                } else {
                        lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
-                                       "2978 Handled SLI_CONFIG "
+                                       "2978 Not handled SLI_CONFIG "
                                        "subsys:x%d, opcode:x%x\n",
                                        subsys, opcode);
                        rc = SLI_CONFIG_NOT_HANDLED;
                }
        }
+
+       /* state reset on not handled new multi-buffer mailbox command */
+       if (rc != SLI_CONFIG_HANDLED)
+               phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE;
+
        return rc;
 }
 
@@ -3844,6 +4104,12 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job)
        dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list,
                                  struct lpfc_dmabuf, list);
        list_del_init(&dmabuf->list);
+
+       /* after dma buffer descriptor setup */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
+                                       mbox_rd, dma_ebuf, sta_pos_addr,
+                                       dmabuf, index);
+
        pbuf = (uint8_t *)dmabuf->virt;
        job->reply->reply_payload_rcv_len =
                sg_copy_from_buffer(job->reply_payload.sg_list,
@@ -3926,6 +4192,11 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job,
                                        dmabuf);
        list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list);
 
+       /* after write dma buffer */
+       lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType,
+                                       mbox_wr, dma_ebuf, sta_pos_addr,
+                                       dmabuf, index);
+
        if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) {
                lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
                                "2968 SLI_CONFIG ext-buffer wr all %d "
@@ -4229,11 +4500,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
 
        /* extended mailbox commands will need an extended buffer */
        if (mbox_req->inExtWLen || mbox_req->outExtWLen) {
-               /* any data for the device? */
-               if (mbox_req->inExtWLen) {
-                       from = pmbx;
-                       ext = from + sizeof(MAILBOX_t);
-               }
+               from = pmbx;
+               ext = from + sizeof(MAILBOX_t);
                pmboxq->context2 = ext;
                pmboxq->in_ext_byte_len =
                        mbox_req->inExtWLen * sizeof(uint32_t);
index c8c2b47ea886f14cb992ec486108a8fafea2adf9..367d2a7a8f2dcf60bf31356c107492a675acfc48 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2010 Emulex.  All rights reserved.                *
+ * Copyright (C) 2010-2011 Emulex.  All rights reserved.                *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -96,7 +96,7 @@ struct get_mgmt_rev {
 };
 
 #define MANAGEMENT_MAJOR_REV   1
-#define MANAGEMENT_MINOR_REV   0
+#define MANAGEMENT_MINOR_REV   1
 
 /* the MgmtRevInfo structure */
 struct MgmtRevInfo {
@@ -248,6 +248,7 @@ struct lpfc_sli_config_emb1_subsys {
 #define COMN_OPCODE_WRITE_OBJECT       0xAC
 #define COMN_OPCODE_READ_OBJECT_LIST   0xAD
 #define COMN_OPCODE_DELETE_OBJECT      0xAE
+#define COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES   0x79
        uint32_t timeout;
        uint32_t request_length;
        uint32_t word9;
@@ -279,6 +280,7 @@ struct lpfc_sli_config_mbox {
        } un;
 };
 
+
 /* driver only */
 #define SLI_CONFIG_NOT_HANDLED         0
 #define SLI_CONFIG_HANDLED             1
index 75e2e569dedefb343e585333559d8e577176d466..c88e556ea62e54769bfdf5850239e262838cff0a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2005 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -82,7 +82,8 @@ lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes)
 static inline void
 lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes)
 {
-       __iowrite32_copy(dest, src, bytes);
+       /* convert bytes in argument list to word count for copy function */
+       __iowrite32_copy(dest, src, bytes / sizeof(uint32_t));
 }
 
 static inline void
index 1e41af8dea743ee9bbb122533335922aac2915de..e159489a1a007e39e02aecd95eda7a09777cf3b0 100644 (file)
@@ -26,7 +26,7 @@ void lpfc_sli_read_link_ste(struct lpfc_hba *);
 void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t);
 void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
-int lpfc_dump_fcoe_param(struct lpfc_hba *, struct lpfcMboxq *);
+int lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *, struct lpfcMboxq *);
 void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
 
@@ -78,6 +78,7 @@ void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *, LPFC_MBOXQ_t *);
+void lpfc_unregister_vfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_enqueue_node(struct lpfc_vport *, struct lpfc_nodelist *);
 void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *);
 struct lpfc_nodelist *lpfc_enable_node(struct lpfc_vport *,
@@ -106,7 +107,7 @@ void lpfc_cleanup(struct lpfc_vport *);
 void lpfc_disc_timeout(unsigned long);
 
 struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
-
+struct lpfc_nodelist * lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
 void lpfc_worker_wake_up(struct lpfc_hba *);
 int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
 int lpfc_do_work(void *);
@@ -209,7 +210,7 @@ void __lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_mbox_cmd_check(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_mbox_dev_check(struct lpfc_hba *);
-int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
+int lpfc_mbox_tmo_val(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *);
 void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
 void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t);
@@ -235,9 +236,11 @@ int lpfc_sli4_redisc_fcf_table(struct lpfc_hba *);
 void lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *);
 void lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *);
 uint16_t lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *);
+void lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *, uint16_t);
 int lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *, uint16_t);
 void lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *, uint16_t);
 int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *, uint16_t);
+void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *);
 
 int lpfc_mem_alloc(struct lpfc_hba *, int align);
 void lpfc_mem_free(struct lpfc_hba *);
@@ -371,6 +374,10 @@ extern struct lpfc_hbq_init *lpfc_hbq_defs[];
 /* SLI4 if_type 2 externs. */
 int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *);
 int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *);
+int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *, uint16_t,
+                                  uint16_t *, uint16_t *);
+int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *, uint16_t,
+                                         uint16_t *, uint16_t *);
 
 /* externs BlockGuard */
 extern char *_dump_buf_data;
@@ -437,7 +444,21 @@ void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
 void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
 struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
        uint32_t);
+void lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *, enum nemb_type,
+       enum mbox_type, enum dma_type, enum sta_type,
+       struct lpfc_dmabuf *, uint32_t);
+void lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *, MAILBOX_t *);
 int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *);
 /* functions to support SR-IOV */
 int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int);
 uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *);
+int lpfc_sli4_queue_create(struct lpfc_hba *);
+void lpfc_sli4_queue_destroy(struct lpfc_hba *);
+void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *,
+                               struct sli4_wcqe_xri_aborted *);
+int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t);
+int lpfc_issue_reg_vfi(struct lpfc_vport *);
+int lpfc_issue_unreg_vfi(struct lpfc_vport *);
+int lpfc_selective_reset(struct lpfc_hba *);
+int lpfc_sli4_read_config(struct lpfc_hba *phba);
+int lpfc_scsi_buf_update(struct lpfc_hba *phba);
index 779b88e1469d01a8d2bcf8dbe28d2faeb7070161..707081d0a2265ad88e7d4b18c25ca0d51d2a9998 100644 (file)
@@ -1856,6 +1856,9 @@ lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
                case 2:
                        c = 'B';
                        break;
+               case 3:
+                       c = 'X';
+                       break;
                default:
                        c = 0;
                        break;
index 35af449991951b416e3ad878b07c6f3e9069096f..d41aeab6d0f03a075aaff0dd60bb6cf433355a63 100644 (file)
@@ -48,6 +48,7 @@
 #include "lpfc_version.h"
 #include "lpfc_compat.h"
 #include "lpfc_debugfs.h"
+#include "lpfc_bsg.h"
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
 /*
@@ -995,6 +996,85 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf,
        return nbytes;
 }
 
+static int
+lpfc_debugfs_dif_err_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t
+lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
+       size_t nbytes, loff_t *ppos)
+{
+       struct dentry *dent = file->f_dentry;
+       struct lpfc_hba *phba = file->private_data;
+       char cbuf[16];
+       int cnt = 0;
+
+       if (dent == phba->debug_writeGuard)
+               cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wgrd_cnt);
+       else if (dent == phba->debug_writeApp)
+               cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wapp_cnt);
+       else if (dent == phba->debug_writeRef)
+               cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_wref_cnt);
+       else if (dent == phba->debug_readApp)
+               cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rapp_cnt);
+       else if (dent == phba->debug_readRef)
+               cnt = snprintf(cbuf, 16, "%u\n", phba->lpfc_injerr_rref_cnt);
+       else if (dent == phba->debug_InjErrLBA)
+               cnt = snprintf(cbuf, 16, "0x%lx\n",
+                                (unsigned long) phba->lpfc_injerr_lba);
+       else
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                        "0547 Unknown debugfs error injection entry\n");
+
+       return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
+}
+
+static ssize_t
+lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
+       size_t nbytes, loff_t *ppos)
+{
+       struct dentry *dent = file->f_dentry;
+       struct lpfc_hba *phba = file->private_data;
+       char dstbuf[32];
+       unsigned long tmp;
+       int size;
+
+       memset(dstbuf, 0, 32);
+       size = (nbytes < 32) ? nbytes : 32;
+       if (copy_from_user(dstbuf, buf, size))
+               return 0;
+
+       if (strict_strtoul(dstbuf, 0, &tmp))
+               return 0;
+
+       if (dent == phba->debug_writeGuard)
+               phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
+       else if (dent == phba->debug_writeApp)
+               phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
+       else if (dent == phba->debug_writeRef)
+               phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
+       else if (dent == phba->debug_readApp)
+               phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
+       else if (dent == phba->debug_readRef)
+               phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
+       else if (dent == phba->debug_InjErrLBA)
+               phba->lpfc_injerr_lba = (sector_t)tmp;
+       else
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                        "0548 Unknown debugfs error injection entry\n");
+
+       return nbytes;
+}
+
+static int
+lpfc_debugfs_dif_err_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
 /**
  * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
  * @inode: The inode pointer that contains a vport pointer.
@@ -1344,8 +1424,8 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
                return 0;
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
-               where = idiag.cmd.data[0];
-               count = idiag.cmd.data[1];
+               where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+               count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
        } else
                return 0;
 
@@ -1390,6 +1470,11 @@ pcicfg_browse:
                len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
                                "%08x ", u32val);
                offset += sizeof(uint32_t);
+               if (offset >= LPFC_PCI_CFG_SIZE) {
+                       len += snprintf(pbuffer+len,
+                                       LPFC_PCI_CFG_SIZE-len, "\n");
+                       break;
+               }
                index -= sizeof(uint32_t);
                if (!index)
                        len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
@@ -1402,8 +1487,11 @@ pcicfg_browse:
        }
 
        /* Set up the offset for next portion of pci cfg read */
-       idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
-       if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+       if (index == 0) {
+               idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
+               if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+                       idiag.offset.last_rd = 0;
+       } else
                idiag.offset.last_rd = 0;
 
        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
@@ -1456,8 +1544,8 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
                if (rc != LPFC_PCI_CFG_RD_CMD_ARG)
                        goto error_out;
                /* Read command from PCI config space, set up command fields */
-               where = idiag.cmd.data[0];
-               count = idiag.cmd.data[1];
+               where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+               count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
                if (count == LPFC_PCI_CFG_BROWSE) {
                        if (where % sizeof(uint32_t))
                                goto error_out;
@@ -1492,9 +1580,9 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
                if (rc != LPFC_PCI_CFG_WR_CMD_ARG)
                        goto error_out;
                /* Write command to PCI config space, read-modify-write */
-               where = idiag.cmd.data[0];
-               count = idiag.cmd.data[1];
-               value = idiag.cmd.data[2];
+               where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX];
+               count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX];
+               value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX];
                /* Sanity checks */
                if ((count != sizeof(uint8_t)) &&
                    (count != sizeof(uint16_t)) &&
@@ -1586,6 +1674,292 @@ error_out:
        return -EINVAL;
 }
 
+/**
+ * lpfc_idiag_baracc_read - idiag debugfs pci bar access read
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba pci bar memory mapped space
+ * according to the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       int offset_label, offset, offset_run, len = 0, index;
+       int bar_num, acc_range, bar_size;
+       char *pbuffer;
+       void __iomem *mem_mapped_bar;
+       uint32_t if_type;
+       struct pci_dev *pdev;
+       uint32_t u32val;
+
+       pdev = phba->pcidev;
+       if (!pdev)
+               return 0;
+
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
+
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
+
+       if (*ppos)
+               return 0;
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
+               bar_num   = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
+               offset    = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
+               acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
+               bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
+       } else
+               return 0;
+
+       if (acc_range == 0)
+               return 0;
+
+       if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+               if (bar_num == IDIAG_BARACC_BAR_0)
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               else if (bar_num == IDIAG_BARACC_BAR_1)
+                       mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
+               else if (bar_num == IDIAG_BARACC_BAR_2)
+                       mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
+               else
+                       return 0;
+       } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+               if (bar_num == IDIAG_BARACC_BAR_0)
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               else
+                       return 0;
+       } else
+               return 0;
+
+       /* Read single PCI bar space register */
+       if (acc_range == SINGLE_WORD) {
+               offset_run = offset;
+               u32val = readl(mem_mapped_bar + offset_run);
+               len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                               "%05x: %08x\n", offset_run, u32val);
+       } else
+               goto baracc_browse;
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+
+baracc_browse:
+
+       /* Browse all PCI bar space registers */
+       offset_label = idiag.offset.last_rd;
+       offset_run = offset_label;
+
+       /* Read PCI bar memory mapped space */
+       len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                       "%05x: ", offset_label);
+       index = LPFC_PCI_BAR_RD_SIZE;
+       while (index > 0) {
+               u32val = readl(mem_mapped_bar + offset_run);
+               len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                               "%08x ", u32val);
+               offset_run += sizeof(uint32_t);
+               if (acc_range == LPFC_PCI_BAR_BROWSE) {
+                       if (offset_run >= bar_size) {
+                               len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+                               break;
+                       }
+               } else {
+                       if (offset_run >= offset +
+                           (acc_range * sizeof(uint32_t))) {
+                               len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+                               break;
+                       }
+               }
+               index -= sizeof(uint32_t);
+               if (!index)
+                       len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n");
+               else if (!(index % (8 * sizeof(uint32_t)))) {
+                       offset_label += (8 * sizeof(uint32_t));
+                       len += snprintf(pbuffer+len,
+                                       LPFC_PCI_BAR_RD_BUF_SIZE-len,
+                                       "\n%05x: ", offset_label);
+               }
+       }
+
+       /* Set up the offset for next portion of pci bar read */
+       if (index == 0) {
+               idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE;
+               if (acc_range == LPFC_PCI_BAR_BROWSE) {
+                       if (idiag.offset.last_rd >= bar_size)
+                               idiag.offset.last_rd = 0;
+               } else {
+                       if (offset_run >= offset +
+                           (acc_range * sizeof(uint32_t)))
+                               idiag.offset.last_rd = offset;
+               }
+       } else {
+               if (acc_range == LPFC_PCI_BAR_BROWSE)
+                       idiag.offset.last_rd = 0;
+               else
+                       idiag.offset.last_rd = offset;
+       }
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and
+ * then perform the syntax check for PCI bar memory mapped space read or
+ * write command accordingly. In the case of PCI bar memory mapped space
+ * read command, it sets up the command in the idiag command struct for
+ * the debugfs read operation. In the case of PCI bar memorpy mapped space
+ * write operation, it executes the write operation into the PCI bar memory
+ * mapped space accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ */
+static ssize_t
+lpfc_idiag_baracc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       uint32_t bar_num, bar_size, offset, value, acc_range;
+       struct pci_dev *pdev;
+       void __iomem *mem_mapped_bar;
+       uint32_t if_type;
+       uint32_t u32val;
+       int rc;
+
+       pdev = phba->pcidev;
+       if (!pdev)
+               return -EFAULT;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+       bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX];
+
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+               if ((bar_num != IDIAG_BARACC_BAR_0) &&
+                   (bar_num != IDIAG_BARACC_BAR_1) &&
+                   (bar_num != IDIAG_BARACC_BAR_2))
+                       goto error_out;
+       } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+               if (bar_num != IDIAG_BARACC_BAR_0)
+                       goto error_out;
+       } else
+               goto error_out;
+
+       if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
+               if (bar_num == IDIAG_BARACC_BAR_0) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF0_BAR0_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               } else if (bar_num == IDIAG_BARACC_BAR_1) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF0_BAR1_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p;
+               } else if (bar_num == IDIAG_BARACC_BAR_2) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF0_BAR2_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p;
+               } else
+                       goto error_out;
+       } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+               if (bar_num == IDIAG_BARACC_BAR_0) {
+                       idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] =
+                               LPFC_PCI_IF2_BAR0_SIZE;
+                       mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p;
+               } else
+                       goto error_out;
+       } else
+               goto error_out;
+
+       offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX];
+       if (offset % sizeof(uint32_t))
+               goto error_out;
+
+       bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX];
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) {
+               /* Sanity check on PCI config read command line arguments */
+               if (rc != LPFC_PCI_BAR_RD_CMD_ARG)
+                       goto error_out;
+               acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX];
+               if (acc_range == LPFC_PCI_BAR_BROWSE) {
+                       if (offset > bar_size - sizeof(uint32_t))
+                               goto error_out;
+                       /* Starting offset to browse */
+                       idiag.offset.last_rd = offset;
+               } else if (acc_range > SINGLE_WORD) {
+                       if (offset + acc_range * sizeof(uint32_t) > bar_size)
+                               goto error_out;
+                       /* Starting offset to browse */
+                       idiag.offset.last_rd = offset;
+               } else if (acc_range != SINGLE_WORD)
+                       goto error_out;
+       } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR ||
+                  idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST ||
+                  idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
+               /* Sanity check on PCI bar write command line arguments */
+               if (rc != LPFC_PCI_BAR_WR_CMD_ARG)
+                       goto error_out;
+               /* Write command to PCI bar space, read-modify-write */
+               acc_range = SINGLE_WORD;
+               value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX];
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) {
+                       writel(value, mem_mapped_bar + offset);
+                       readl(mem_mapped_bar + offset);
+               }
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) {
+                       u32val = readl(mem_mapped_bar + offset);
+                       u32val |= value;
+                       writel(u32val, mem_mapped_bar + offset);
+                       readl(mem_mapped_bar + offset);
+               }
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) {
+                       u32val = readl(mem_mapped_bar + offset);
+                       u32val &= ~value;
+                       writel(u32val, mem_mapped_bar + offset);
+                       readl(mem_mapped_bar + offset);
+               }
+       } else
+               /* All other opecodes are illegal for now */
+               goto error_out;
+
+       return nbytes;
+error_out:
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
 /**
  * lpfc_idiag_queinfo_read - idiag debugfs read queue information
  * @file: The file pointer to read from.
@@ -1622,7 +1996,8 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
        /* Get slow-path event queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Slow-path EQ information:\n");
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.sp_eq) {
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "\tEQID[%02d], "
                        "QE-COUNT[%04d], QE-SIZE[%04d], "
                        "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
@@ -1631,12 +2006,17 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                        phba->sli4_hba.sp_eq->entry_size,
                        phba->sli4_hba.sp_eq->host_index,
                        phba->sli4_hba.sp_eq->hba_index);
+       }
 
        /* Get fast-path event queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Fast-path EQ information:\n");
-       for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) {
-               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.fp_eq) {
+               for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count;
+                    fcp_qidx++) {
+                       if (phba->sli4_hba.fp_eq[fcp_qidx]) {
+                               len += snprintf(pbuffer+len,
+                                       LPFC_QUE_INFO_GET_BUF_SIZE-len,
                                "\tEQID[%02d], "
                                "QE-COUNT[%04d], QE-SIZE[%04d], "
                                "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
@@ -1645,16 +2025,19 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                                phba->sli4_hba.fp_eq[fcp_qidx]->entry_size,
                                phba->sli4_hba.fp_eq[fcp_qidx]->host_index,
                                phba->sli4_hba.fp_eq[fcp_qidx]->hba_index);
+                       }
+               }
        }
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
 
        /* Get mailbox complete queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Slow-path MBX CQ information:\n");
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.mbx_cq) {
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Associated EQID[%02d]:\n",
                        phba->sli4_hba.mbx_cq->assoc_qid);
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "\tCQID[%02d], "
                        "QE-COUNT[%04d], QE-SIZE[%04d], "
                        "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
@@ -1663,14 +2046,16 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                        phba->sli4_hba.mbx_cq->entry_size,
                        phba->sli4_hba.mbx_cq->host_index,
                        phba->sli4_hba.mbx_cq->hba_index);
+       }
 
        /* Get slow-path complete queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Slow-path ELS CQ information:\n");
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.els_cq) {
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Associated EQID[%02d]:\n",
                        phba->sli4_hba.els_cq->assoc_qid);
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "\tCQID [%02d], "
                        "QE-COUNT[%04d], QE-SIZE[%04d], "
                        "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
@@ -1679,16 +2064,21 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                        phba->sli4_hba.els_cq->entry_size,
                        phba->sli4_hba.els_cq->host_index,
                        phba->sli4_hba.els_cq->hba_index);
+       }
 
        /* Get fast-path complete queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Fast-path FCP CQ information:\n");
        fcp_qidx = 0;
-       do {
-               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.fcp_cq) {
+               do {
+                       if (phba->sli4_hba.fcp_cq[fcp_qidx]) {
+                               len += snprintf(pbuffer+len,
+                                       LPFC_QUE_INFO_GET_BUF_SIZE-len,
                                "Associated EQID[%02d]:\n",
                                phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid);
-               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+                               len += snprintf(pbuffer+len,
+                                       LPFC_QUE_INFO_GET_BUF_SIZE-len,
                                "\tCQID[%02d], "
                                "QE-COUNT[%04d], QE-SIZE[%04d], "
                                "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
@@ -1697,16 +2087,20 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                                phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size,
                                phba->sli4_hba.fcp_cq[fcp_qidx]->host_index,
                                phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index);
-       } while (++fcp_qidx < phba->cfg_fcp_eq_count);
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+                       }
+               } while (++fcp_qidx < phba->cfg_fcp_eq_count);
+               len += snprintf(pbuffer+len,
+                               LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+       }
 
        /* Get mailbox queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Slow-path MBX MQ information:\n");
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.mbx_wq) {
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Associated CQID[%02d]:\n",
                        phba->sli4_hba.mbx_wq->assoc_qid);
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "\tWQID[%02d], "
                        "QE-COUNT[%04d], QE-SIZE[%04d], "
                        "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
@@ -1715,14 +2109,16 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                        phba->sli4_hba.mbx_wq->entry_size,
                        phba->sli4_hba.mbx_wq->host_index,
                        phba->sli4_hba.mbx_wq->hba_index);
+       }
 
        /* Get slow-path work queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Slow-path ELS WQ information:\n");
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.els_wq) {
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Associated CQID[%02d]:\n",
                        phba->sli4_hba.els_wq->assoc_qid);
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "\tWQID[%02d], "
                        "QE-COUNT[%04d], QE-SIZE[%04d], "
                        "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
@@ -1731,15 +2127,22 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                        phba->sli4_hba.els_wq->entry_size,
                        phba->sli4_hba.els_wq->host_index,
                        phba->sli4_hba.els_wq->hba_index);
+       }
 
        /* Get fast-path work queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Fast-path FCP WQ information:\n");
-       for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) {
-               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.fcp_wq) {
+               for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count;
+                    fcp_qidx++) {
+                       if (!phba->sli4_hba.fcp_wq[fcp_qidx])
+                               continue;
+                       len += snprintf(pbuffer+len,
+                                       LPFC_QUE_INFO_GET_BUF_SIZE-len,
                                "Associated CQID[%02d]:\n",
                                phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid);
-               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+                       len += snprintf(pbuffer+len,
+                                       LPFC_QUE_INFO_GET_BUF_SIZE-len,
                                "\tWQID[%02d], "
                                "QE-COUNT[%04d], WQE-SIZE[%04d], "
                                "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
@@ -1748,16 +2151,19 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                                phba->sli4_hba.fcp_wq[fcp_qidx]->entry_size,
                                phba->sli4_hba.fcp_wq[fcp_qidx]->host_index,
                                phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index);
+               }
+               len += snprintf(pbuffer+len,
+                               LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
        }
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
 
        /* Get receive queue information */
        len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Slow-path RQ information:\n");
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+       if (phba->sli4_hba.hdr_rq && phba->sli4_hba.dat_rq) {
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "Associated CQID[%02d]:\n",
                        phba->sli4_hba.hdr_rq->assoc_qid);
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "\tHQID[%02d], "
                        "QE-COUNT[%04d], QE-SIZE[%04d], "
                        "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
@@ -1766,7 +2172,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                        phba->sli4_hba.hdr_rq->entry_size,
                        phba->sli4_hba.hdr_rq->host_index,
                        phba->sli4_hba.hdr_rq->hba_index);
-       len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+               len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
                        "\tDQID[%02d], "
                        "QE-COUNT[%04d], QE-SIZE[%04d], "
                        "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
@@ -1775,7 +2181,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
                        phba->sli4_hba.dat_rq->entry_size,
                        phba->sli4_hba.dat_rq->host_index,
                        phba->sli4_hba.dat_rq->hba_index);
-
+       }
        return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
 }
 
@@ -1888,8 +2294,8 @@ lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes,
                return 0;
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
-               index = idiag.cmd.data[2];
-               count = idiag.cmd.data[3];
+               index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
+               count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
                pque = (struct lpfc_queue *)idiag.ptr_private;
        } else
                return 0;
@@ -1961,12 +2367,12 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                return rc;
 
        /* Get and sanity check on command feilds */
-       quetp  = idiag.cmd.data[0];
-       queid  = idiag.cmd.data[1];
-       index  = idiag.cmd.data[2];
-       count  = idiag.cmd.data[3];
-       offset = idiag.cmd.data[4];
-       value  = idiag.cmd.data[5];
+       quetp  = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX];
+       queid  = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX];
+       index  = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX];
+       count  = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX];
+       offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX];
+       value  = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX];
 
        /* Sanity check on command line arguments */
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
@@ -1985,7 +2391,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
        switch (quetp) {
        case LPFC_IDIAG_EQ:
                /* Slow-path event queue */
-               if (phba->sli4_hba.sp_eq->queue_id == queid) {
+               if (phba->sli4_hba.sp_eq &&
+                   phba->sli4_hba.sp_eq->queue_id == queid) {
                        /* Sanity check */
                        rc = lpfc_idiag_que_param_check(
                                        phba->sli4_hba.sp_eq, index, count);
@@ -1995,23 +2402,29 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        goto pass_check;
                }
                /* Fast-path event queue */
-               for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) {
-                       if (phba->sli4_hba.fp_eq[qidx]->queue_id == queid) {
-                               /* Sanity check */
-                               rc = lpfc_idiag_que_param_check(
+               if (phba->sli4_hba.fp_eq) {
+                       for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) {
+                               if (phba->sli4_hba.fp_eq[qidx] &&
+                                   phba->sli4_hba.fp_eq[qidx]->queue_id ==
+                                   queid) {
+                                       /* Sanity check */
+                                       rc = lpfc_idiag_que_param_check(
                                                phba->sli4_hba.fp_eq[qidx],
                                                index, count);
-                               if (rc)
-                                       goto error_out;
-                               idiag.ptr_private = phba->sli4_hba.fp_eq[qidx];
-                               goto pass_check;
+                                       if (rc)
+                                               goto error_out;
+                                       idiag.ptr_private =
+                                               phba->sli4_hba.fp_eq[qidx];
+                                       goto pass_check;
+                               }
                        }
                }
                goto error_out;
                break;
        case LPFC_IDIAG_CQ:
                /* MBX complete queue */
-               if (phba->sli4_hba.mbx_cq->queue_id == queid) {
+               if (phba->sli4_hba.mbx_cq &&
+                   phba->sli4_hba.mbx_cq->queue_id == queid) {
                        /* Sanity check */
                        rc = lpfc_idiag_que_param_check(
                                        phba->sli4_hba.mbx_cq, index, count);
@@ -2021,7 +2434,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        goto pass_check;
                }
                /* ELS complete queue */
-               if (phba->sli4_hba.els_cq->queue_id == queid) {
+               if (phba->sli4_hba.els_cq &&
+                   phba->sli4_hba.els_cq->queue_id == queid) {
                        /* Sanity check */
                        rc = lpfc_idiag_que_param_check(
                                        phba->sli4_hba.els_cq, index, count);
@@ -2031,25 +2445,30 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        goto pass_check;
                }
                /* FCP complete queue */
-               qidx = 0;
-               do {
-                       if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) {
-                               /* Sanity check */
-                               rc = lpfc_idiag_que_param_check(
+               if (phba->sli4_hba.fcp_cq) {
+                       qidx = 0;
+                       do {
+                               if (phba->sli4_hba.fcp_cq[qidx] &&
+                                   phba->sli4_hba.fcp_cq[qidx]->queue_id ==
+                                   queid) {
+                                       /* Sanity check */
+                                       rc = lpfc_idiag_que_param_check(
                                                phba->sli4_hba.fcp_cq[qidx],
                                                index, count);
-                               if (rc)
-                                       goto error_out;
-                               idiag.ptr_private =
+                                       if (rc)
+                                               goto error_out;
+                                       idiag.ptr_private =
                                                phba->sli4_hba.fcp_cq[qidx];
-                               goto pass_check;
-                       }
-               } while (++qidx < phba->cfg_fcp_eq_count);
+                                       goto pass_check;
+                               }
+                       } while (++qidx < phba->cfg_fcp_eq_count);
+               }
                goto error_out;
                break;
        case LPFC_IDIAG_MQ:
                /* MBX work queue */
-               if (phba->sli4_hba.mbx_wq->queue_id == queid) {
+               if (phba->sli4_hba.mbx_wq &&
+                   phba->sli4_hba.mbx_wq->queue_id == queid) {
                        /* Sanity check */
                        rc = lpfc_idiag_que_param_check(
                                        phba->sli4_hba.mbx_wq, index, count);
@@ -2058,10 +2477,12 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        idiag.ptr_private = phba->sli4_hba.mbx_wq;
                        goto pass_check;
                }
+               goto error_out;
                break;
        case LPFC_IDIAG_WQ:
                /* ELS work queue */
-               if (phba->sli4_hba.els_wq->queue_id == queid) {
+               if (phba->sli4_hba.els_wq &&
+                   phba->sli4_hba.els_wq->queue_id == queid) {
                        /* Sanity check */
                        rc = lpfc_idiag_que_param_check(
                                        phba->sli4_hba.els_wq, index, count);
@@ -2071,24 +2492,30 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        goto pass_check;
                }
                /* FCP work queue */
-               for (qidx = 0; qidx < phba->cfg_fcp_wq_count; qidx++) {
-                       if (phba->sli4_hba.fcp_wq[qidx]->queue_id == queid) {
-                               /* Sanity check */
-                               rc = lpfc_idiag_que_param_check(
+               if (phba->sli4_hba.fcp_wq) {
+                       for (qidx = 0; qidx < phba->cfg_fcp_wq_count; qidx++) {
+                               if (!phba->sli4_hba.fcp_wq[qidx])
+                                       continue;
+                               if (phba->sli4_hba.fcp_wq[qidx]->queue_id ==
+                                   queid) {
+                                       /* Sanity check */
+                                       rc = lpfc_idiag_que_param_check(
                                                phba->sli4_hba.fcp_wq[qidx],
                                                index, count);
-                               if (rc)
-                                       goto error_out;
-                               idiag.ptr_private =
-                                       phba->sli4_hba.fcp_wq[qidx];
-                               goto pass_check;
+                                       if (rc)
+                                               goto error_out;
+                                       idiag.ptr_private =
+                                               phba->sli4_hba.fcp_wq[qidx];
+                                       goto pass_check;
+                               }
                        }
                }
                goto error_out;
                break;
        case LPFC_IDIAG_RQ:
                /* HDR queue */
-               if (phba->sli4_hba.hdr_rq->queue_id == queid) {
+               if (phba->sli4_hba.hdr_rq &&
+                   phba->sli4_hba.hdr_rq->queue_id == queid) {
                        /* Sanity check */
                        rc = lpfc_idiag_que_param_check(
                                        phba->sli4_hba.hdr_rq, index, count);
@@ -2098,7 +2525,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
                        goto pass_check;
                }
                /* DAT queue */
-               if (phba->sli4_hba.dat_rq->queue_id == queid) {
+               if (phba->sli4_hba.dat_rq &&
+                   phba->sli4_hba.dat_rq->queue_id == queid) {
                        /* Sanity check */
                        rc = lpfc_idiag_que_param_check(
                                        phba->sli4_hba.dat_rq, index, count);
@@ -2235,7 +2663,7 @@ lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes,
                return 0;
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD)
-               drb_reg_id = idiag.cmd.data[0];
+               drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
        else
                return 0;
 
@@ -2274,7 +2702,7 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
 {
        struct lpfc_debug *debug = file->private_data;
        struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
-       uint32_t drb_reg_id, value, reg_val;
+       uint32_t drb_reg_id, value, reg_val = 0;
        void __iomem *drb_reg;
        int rc;
 
@@ -2286,8 +2714,8 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
                return rc;
 
        /* Sanity check on command line arguments */
-       drb_reg_id = idiag.cmd.data[0];
-       value = idiag.cmd.data[1];
+       drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX];
+       value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX];
 
        if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
            idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
@@ -2347,22 +2775,695 @@ error_out:
        return -EINVAL;
 }
 
-#undef lpfc_debugfs_op_disc_trc
-static const struct file_operations lpfc_debugfs_op_disc_trc = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_disc_trc_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+/**
+ * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers
+ * @phba: The pointer to hba structure.
+ * @pbuffer: The pointer to the buffer to copy the data to.
+ * @len: The lenght of bytes to copied.
+ * @drbregid: The id to doorbell registers.
+ *
+ * Description:
+ * This routine reads a control register and copies its content to the
+ * user buffer pointed to by @pbuffer.
+ *
+ * Returns:
+ * This function returns the amount of data that was copied into @pbuffer.
+ **/
+static int
+lpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
+                          int len, uint32_t ctlregid)
+{
 
-#undef lpfc_debugfs_op_nodelist
-static const struct file_operations lpfc_debugfs_op_nodelist = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_nodelist_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
+       if (!pbuffer)
+               return 0;
+
+       switch (ctlregid) {
+       case LPFC_CTL_PORT_SEM:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port SemReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_SEM_OFFSET));
+               break;
+       case LPFC_CTL_PORT_STA:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port StaReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_STA_OFFSET));
+               break;
+       case LPFC_CTL_PORT_CTL:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port CtlReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_CTL_OFFSET));
+               break;
+       case LPFC_CTL_PORT_ER1:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port Er1Reg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_ER1_OFFSET));
+               break;
+       case LPFC_CTL_PORT_ER2:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "Port Er2Reg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PORT_ER2_OFFSET));
+               break;
+       case LPFC_CTL_PDEV_CTL:
+               len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len,
+                               "PDev CtlReg:   0x%08x\n",
+                               readl(phba->sli4_hba.conf_regs_memmap_p +
+                                     LPFC_CTL_PDEV_CTL_OFFSET));
+               break;
+       default:
+               break;
+       }
+       return len;
+}
+
+/**
+ * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba port and device registers according
+ * to the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       uint32_t ctl_reg_id, i;
+       char *pbuffer;
+       int len = 0;
+
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
+
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
+
+       if (*ppos)
+               return 0;
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD)
+               ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
+       else
+               return 0;
+
+       if (ctl_reg_id == LPFC_CTL_ACC_ALL)
+               for (i = 1; i <= LPFC_CTL_MAX; i++)
+                       len = lpfc_idiag_ctlacc_read_reg(phba,
+                                                        pbuffer, len, i);
+       else
+               len = lpfc_idiag_ctlacc_read_reg(phba,
+                                                pbuffer, len, ctl_reg_id);
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for port and device control register read (dump)
+ * or write (set) command accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_ctlacc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       uint32_t ctl_reg_id, value, reg_val = 0;
+       void __iomem *ctl_reg;
+       int rc;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       /* Sanity check on command line arguments */
+       ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX];
+       value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX];
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+               if (rc != LPFC_CTL_ACC_WR_CMD_ARG)
+                       goto error_out;
+               if (ctl_reg_id > LPFC_CTL_MAX)
+                       goto error_out;
+       } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) {
+               if (rc != LPFC_CTL_ACC_RD_CMD_ARG)
+                       goto error_out;
+               if ((ctl_reg_id > LPFC_CTL_MAX) &&
+                   (ctl_reg_id != LPFC_CTL_ACC_ALL))
+                       goto error_out;
+       } else
+               goto error_out;
+
+       /* Perform the write access operation */
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST ||
+           idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+               switch (ctl_reg_id) {
+               case LPFC_CTL_PORT_SEM:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_SEM_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_STA:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_STA_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_CTL:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_CTL_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_ER1:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_ER1_OFFSET;
+                       break;
+               case LPFC_CTL_PORT_ER2:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PORT_ER2_OFFSET;
+                       break;
+               case LPFC_CTL_PDEV_CTL:
+                       ctl_reg = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_CTL_PDEV_CTL_OFFSET;
+                       break;
+               default:
+                       goto error_out;
+               }
+
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR)
+                       reg_val = value;
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) {
+                       reg_val = readl(ctl_reg);
+                       reg_val |= value;
+               }
+               if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) {
+                       reg_val = readl(ctl_reg);
+                       reg_val &= ~value;
+               }
+               writel(reg_val, ctl_reg);
+               readl(ctl_reg); /* flush */
+       }
+       return nbytes;
+
+error_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup
+ * @phba: Pointer to HBA context object.
+ * @pbuffer: Pointer to data buffer.
+ *
+ * Description:
+ * This routine gets the driver mailbox access debugfs setup information.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static int
+lpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer)
+{
+       uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
+       int len = 0;
+
+       mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_dump_map: 0x%08x\n", mbx_dump_map);
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_dump_cnt: %04d\n", mbx_dump_cnt);
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_word_cnt: %04d\n", mbx_word_cnt);
+       len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len,
+                       "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd);
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba driver mailbox access debugfs setup
+ * information.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       char *pbuffer;
+       int len = 0;
+
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
+
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
+
+       if (*ppos)
+               return 0;
+
+       if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) &&
+           (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP))
+               return 0;
+
+       len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer);
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for driver mailbox command (dump) and sets up the
+ * necessary states in the idiag command struct accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd;
+       int rc;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       /* Sanity check on command line arguments */
+       mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) {
+               if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL))
+                       goto error_out;
+               if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) &&
+                   (mbx_dump_map != LPFC_MBX_DMP_ALL))
+                       goto error_out;
+               if (mbx_word_cnt > sizeof(MAILBOX_t))
+                       goto error_out;
+       } else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) {
+               if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL))
+                       goto error_out;
+               if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) &&
+                   (mbx_dump_map != LPFC_MBX_DMP_ALL))
+                       goto error_out;
+               if (mbx_word_cnt > (BSG_MBOX_SIZE)/4)
+                       goto error_out;
+               if (mbx_mbox_cmd != 0x9b)
+                       goto error_out;
+       } else
+               goto error_out;
+
+       if (mbx_word_cnt == 0)
+               goto error_out;
+       if (rc != LPFC_MBX_DMP_ARG)
+               goto error_out;
+       if (mbx_mbox_cmd & ~0xff)
+               goto error_out;
+
+       /* condition for stop mailbox dump */
+       if (mbx_dump_cnt == 0)
+               goto reset_out;
+
+       return nbytes;
+
+reset_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return nbytes;
+
+error_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_extacc_avail_get - get the available extents information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the available extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+       uint16_t ext_cnt, ext_size;
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\nAvailable Extents Information:\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available VPI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available VFI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available RPI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tPort Available XRI extents: ");
+       lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI,
+                                      &ext_cnt, &ext_size);
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "Count %3d, Size %3d\n", ext_cnt, ext_size);
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_extacc_alloc_get - get the allocated extents information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the allocated extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+       uint16_t ext_cnt, ext_size;
+       int rc;
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\nAllocated Extents Information:\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated VPI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated VFI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated RPI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tHost Allocated XRI extents: ");
+       rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI,
+                                           &ext_cnt, &ext_size);
+       if (!rc)
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "Port %d Extent %3d, Size %3d\n",
+                               phba->brd_no, ext_cnt, ext_size);
+       else
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "N/A\n");
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_extacc_drivr_get - get driver extent information
+ * @phba: pointer to lpfc hba data structure.
+ * @pbuffer: pointer to internal buffer.
+ * @len: length into the internal buffer data has been copied.
+ *
+ * Description:
+ * This routine is to get the driver extent information.
+ *
+ * Returns:
+ * overall lenth of the data read into the internal buffer.
+ **/
+static int
+lpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len)
+{
+       struct lpfc_rsrc_blks *rsrc_blks;
+       int index;
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\nDriver Extents Information:\n");
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tVPI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tVFI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list,
+                           list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tRPI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list,
+                           list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+
+       len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                       "\tXRI extents:\n");
+       index = 0;
+       list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list,
+                           list) {
+               len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len,
+                               "\t\tBlock %3d: Start %4d, Count %4d\n",
+                               index, rsrc_blks->rsrc_start,
+                               rsrc_blks->rsrc_size);
+               index++;
+       }
+
+       return len;
+}
+
+/**
+ * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and then
+ * perform the syntax check for extent information access commands and sets
+ * up the necessary states in the idiag command struct accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ **/
+static ssize_t
+lpfc_idiag_extacc_write(struct file *file, const char __user *buf,
+                       size_t nbytes, loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       uint32_t ext_map;
+       int rc;
+
+       /* This is a user write operation */
+       debug->op = LPFC_IDIAG_OP_WR;
+
+       rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+       if (rc < 0)
+               return rc;
+
+       ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
+
+       if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
+               goto error_out;
+       if (rc != LPFC_EXT_ACC_CMD_ARG)
+               goto error_out;
+       if (!(ext_map & LPFC_EXT_ACC_ALL))
+               goto error_out;
+
+       return nbytes;
+error_out:
+       /* Clean out command structure on command error out */
+       memset(&idiag, 0, sizeof(idiag));
+       return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_extacc_read - idiag debugfs read access to extent information
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the proper extent information according to
+ * the idiag command, and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes,
+                      loff_t *ppos)
+{
+       struct lpfc_debug *debug = file->private_data;
+       struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+       char *pbuffer;
+       uint32_t ext_map;
+       int len = 0;
+
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
+
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
+       if (*ppos)
+               return 0;
+       if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD)
+               return 0;
+
+       ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX];
+       if (ext_map & LPFC_EXT_ACC_AVAIL)
+               len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len);
+       if (ext_map & LPFC_EXT_ACC_ALLOC)
+               len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len);
+       if (ext_map & LPFC_EXT_ACC_DRIVR)
+               len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len);
+
+       return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+#undef lpfc_debugfs_op_disc_trc
+static const struct file_operations lpfc_debugfs_op_disc_trc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_disc_trc_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_nodelist
+static const struct file_operations lpfc_debugfs_op_nodelist = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_nodelist_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
 };
 
 #undef lpfc_debugfs_op_hbqinfo
@@ -2412,6 +3513,16 @@ static const struct file_operations lpfc_debugfs_op_dumpDif = {
        .release =      lpfc_debugfs_dumpDataDif_release,
 };
 
+#undef lpfc_debugfs_op_dif_err
+static const struct file_operations lpfc_debugfs_op_dif_err = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_dif_err_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_dif_err_read,
+       .write =        lpfc_debugfs_dif_err_write,
+       .release =      lpfc_debugfs_dif_err_release,
+};
+
 #undef lpfc_debugfs_op_slow_ring_trc
 static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
        .owner =        THIS_MODULE,
@@ -2437,6 +3548,16 @@ static const struct file_operations lpfc_idiag_op_pciCfg = {
        .release =      lpfc_idiag_cmd_release,
 };
 
+#undef lpfc_idiag_op_barAcc
+static const struct file_operations lpfc_idiag_op_barAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_baracc_read,
+       .write =        lpfc_idiag_baracc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
 #undef lpfc_idiag_op_queInfo
 static const struct file_operations lpfc_idiag_op_queInfo = {
        .owner =        THIS_MODULE,
@@ -2445,7 +3566,7 @@ static const struct file_operations lpfc_idiag_op_queInfo = {
        .release =      lpfc_idiag_release,
 };
 
-#undef lpfc_idiag_op_queacc
+#undef lpfc_idiag_op_queAcc
 static const struct file_operations lpfc_idiag_op_queAcc = {
        .owner =        THIS_MODULE,
        .open =         lpfc_idiag_open,
@@ -2455,7 +3576,7 @@ static const struct file_operations lpfc_idiag_op_queAcc = {
        .release =      lpfc_idiag_cmd_release,
 };
 
-#undef lpfc_idiag_op_drbacc
+#undef lpfc_idiag_op_drbAcc
 static const struct file_operations lpfc_idiag_op_drbAcc = {
        .owner =        THIS_MODULE,
        .open =         lpfc_idiag_open,
@@ -2465,7 +3586,233 @@ static const struct file_operations lpfc_idiag_op_drbAcc = {
        .release =      lpfc_idiag_cmd_release,
 };
 
+#undef lpfc_idiag_op_ctlAcc
+static const struct file_operations lpfc_idiag_op_ctlAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_ctlacc_read,
+       .write =        lpfc_idiag_ctlacc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_mbxAcc
+static const struct file_operations lpfc_idiag_op_mbxAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_mbxacc_read,
+       .write =        lpfc_idiag_mbxacc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_extAcc
+static const struct file_operations lpfc_idiag_op_extAcc = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_idiag_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_idiag_extacc_read,
+       .write =        lpfc_idiag_extacc_write,
+       .release =      lpfc_idiag_cmd_release,
+};
+
+#endif
+
+/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
+ * @phba: Pointer to HBA context object.
+ * @dmabuf: Pointer to a DMA buffer descriptor.
+ *
+ * Description:
+ * This routine dump a bsg pass-through non-embedded mailbox command with
+ * external buffer.
+ **/
+void
+lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp,
+                               enum mbox_type mbox_tp, enum dma_type dma_tp,
+                               enum sta_type sta_tp,
+                               struct lpfc_dmabuf *dmabuf, uint32_t ext_buf)
+{
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt;
+       char line_buf[LPFC_MBX_ACC_LBUF_SZ];
+       int len = 0;
+       uint32_t do_dump = 0;
+       uint32_t *pword;
+       uint32_t i;
+
+       if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)
+               return;
+
+       mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) ||
+           (*mbx_dump_cnt == 0) ||
+           (*mbx_word_cnt == 0))
+               return;
+
+       if (*mbx_mbox_cmd != 0x9B)
+               return;
+
+       if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) {
+                       do_dump |= LPFC_BSG_DMP_MBX_RD_MBX;
+                       printk(KERN_ERR "\nRead mbox command (x%x), "
+                              "nemb:0x%x, extbuf_cnt:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+       if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) {
+                       do_dump |= LPFC_BSG_DMP_MBX_RD_BUF;
+                       printk(KERN_ERR "\nRead mbox buffer (x%x), "
+                              "nemb:0x%x, extbuf_seq:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+       if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) {
+                       do_dump |= LPFC_BSG_DMP_MBX_WR_MBX;
+                       printk(KERN_ERR "\nWrite mbox command (x%x), "
+                              "nemb:0x%x, extbuf_cnt:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+       if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) {
+               if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) {
+                       do_dump |= LPFC_BSG_DMP_MBX_WR_BUF;
+                       printk(KERN_ERR "\nWrite mbox buffer (x%x), "
+                              "nemb:0x%x, extbuf_seq:%d:\n",
+                              sta_tp, nemb_tp, ext_buf);
+               }
+       }
+
+       /* dump buffer content */
+       if (do_dump) {
+               pword = (uint32_t *)dmabuf->virt;
+               for (i = 0; i < *mbx_word_cnt; i++) {
+                       if (!(i % 8)) {
+                               if (i != 0)
+                                       printk(KERN_ERR "%s\n", line_buf);
+                               len = 0;
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%03d: ", i);
+                       }
+                       len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
+                                       "%08x ", (uint32_t)*pword);
+                       pword++;
+               }
+               if ((i - 1) % 8)
+                       printk(KERN_ERR "%s\n", line_buf);
+               (*mbx_dump_cnt)--;
+       }
+
+       /* Clean out command structure on reaching dump count */
+       if (*mbx_dump_cnt == 0)
+               memset(&idiag, 0, sizeof(idiag));
+       return;
+#endif
+}
+
+/* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command
+ * @phba: Pointer to HBA context object.
+ * @dmabuf: Pointer to a DMA buffer descriptor.
+ *
+ * Description:
+ * This routine dump a pass-through non-embedded mailbox command from issue
+ * mailbox command.
+ **/
+void
+lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox)
+{
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd;
+       char line_buf[LPFC_MBX_ACC_LBUF_SZ];
+       int len = 0;
+       uint32_t *pword;
+       uint8_t *pbyte;
+       uint32_t i, j;
+
+       if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP)
+               return;
+
+       mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX];
+       mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX];
+       mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX];
+       mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX];
+
+       if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) ||
+           (*mbx_dump_cnt == 0) ||
+           (*mbx_word_cnt == 0))
+               return;
+
+       if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) &&
+           (*mbx_mbox_cmd != pmbox->mbxCommand))
+               return;
+
+       /* dump buffer content */
+       if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) {
+               printk(KERN_ERR "Mailbox command:0x%x dump by word:\n",
+                      pmbox->mbxCommand);
+               pword = (uint32_t *)pmbox;
+               for (i = 0; i < *mbx_word_cnt; i++) {
+                       if (!(i % 8)) {
+                               if (i != 0)
+                                       printk(KERN_ERR "%s\n", line_buf);
+                               len = 0;
+                               memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%03d: ", i);
+                       }
+                       len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len,
+                                       "%08x ",
+                                       ((uint32_t)*pword) & 0xffffffff);
+                       pword++;
+               }
+               if ((i - 1) % 8)
+                       printk(KERN_ERR "%s\n", line_buf);
+               printk(KERN_ERR "\n");
+       }
+       if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) {
+               printk(KERN_ERR "Mailbox command:0x%x dump by byte:\n",
+                      pmbox->mbxCommand);
+               pbyte = (uint8_t *)pmbox;
+               for (i = 0; i < *mbx_word_cnt; i++) {
+                       if (!(i % 8)) {
+                               if (i != 0)
+                                       printk(KERN_ERR "%s\n", line_buf);
+                               len = 0;
+                               memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ);
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%03d: ", i);
+                       }
+                       for (j = 0; j < 4; j++) {
+                               len += snprintf(line_buf+len,
+                                               LPFC_MBX_ACC_LBUF_SZ-len,
+                                               "%02x",
+                                               ((uint8_t)*pbyte) & 0xff);
+                               pbyte++;
+                       }
+                       len += snprintf(line_buf+len,
+                                       LPFC_MBX_ACC_LBUF_SZ-len, " ");
+               }
+               if ((i - 1) % 8)
+                       printk(KERN_ERR "%s\n", line_buf);
+               printk(KERN_ERR "\n");
+       }
+       (*mbx_dump_cnt)--;
+
+       /* Clean out command structure on reaching dump count */
+       if (*mbx_dump_cnt == 0)
+               memset(&idiag, 0, sizeof(idiag));
+       return;
 #endif
+}
 
 /**
  * lpfc_debugfs_initialize - Initialize debugfs for a vport
@@ -2584,6 +3931,74 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                        goto debug_failed;
                }
 
+               /* Setup DIF Error Injections */
+               snprintf(name, sizeof(name), "InjErrLBA");
+               phba->debug_InjErrLBA =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                       phba->hba_debugfs_root,
+                       phba, &lpfc_debugfs_op_dif_err);
+               if (!phba->debug_InjErrLBA) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                               "0807 Cannot create debugfs InjErrLBA\n");
+                       goto debug_failed;
+               }
+               phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+
+               snprintf(name, sizeof(name), "writeGuardInjErr");
+               phba->debug_writeGuard =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                       phba->hba_debugfs_root,
+                       phba, &lpfc_debugfs_op_dif_err);
+               if (!phba->debug_writeGuard) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                               "0802 Cannot create debugfs writeGuard\n");
+                       goto debug_failed;
+               }
+
+               snprintf(name, sizeof(name), "writeAppInjErr");
+               phba->debug_writeApp =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                       phba->hba_debugfs_root,
+                       phba, &lpfc_debugfs_op_dif_err);
+               if (!phba->debug_writeApp) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                               "0803 Cannot create debugfs writeApp\n");
+                       goto debug_failed;
+               }
+
+               snprintf(name, sizeof(name), "writeRefInjErr");
+               phba->debug_writeRef =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                       phba->hba_debugfs_root,
+                       phba, &lpfc_debugfs_op_dif_err);
+               if (!phba->debug_writeRef) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                               "0804 Cannot create debugfs writeRef\n");
+                       goto debug_failed;
+               }
+
+               snprintf(name, sizeof(name), "readAppInjErr");
+               phba->debug_readApp =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                       phba->hba_debugfs_root,
+                       phba, &lpfc_debugfs_op_dif_err);
+               if (!phba->debug_readApp) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                               "0805 Cannot create debugfs readApp\n");
+                       goto debug_failed;
+               }
+
+               snprintf(name, sizeof(name), "readRefInjErr");
+               phba->debug_readRef =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                       phba->hba_debugfs_root,
+                       phba, &lpfc_debugfs_op_dif_err);
+               if (!phba->debug_readRef) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                               "0806 Cannot create debugfs readApp\n");
+                       goto debug_failed;
+               }
+
                /* Setup slow ring trace */
                if (lpfc_debugfs_max_slow_ring_trc) {
                        num = lpfc_debugfs_max_slow_ring_trc - 1;
@@ -2690,7 +4105,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                                 vport, &lpfc_debugfs_op_nodelist);
        if (!vport->debug_nodelist) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-                                "0409 Can't create debugfs nodelist\n");
+                                "2985 Can't create debugfs nodelist\n");
                goto debug_failed;
        }
 
@@ -2727,6 +4142,20 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                idiag.offset.last_rd = 0;
        }
 
+       /* iDiag PCI BAR access */
+       snprintf(name, sizeof(name), "barAcc");
+       if (!phba->idiag_bar_acc) {
+               phba->idiag_bar_acc =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                               phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
+               if (!phba->idiag_bar_acc) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                       "3056 Can't create idiag debugfs\n");
+                       goto debug_failed;
+               }
+               idiag.offset.last_rd = 0;
+       }
+
        /* iDiag get PCI function queue information */
        snprintf(name, sizeof(name), "queInfo");
        if (!phba->idiag_que_info) {
@@ -2766,6 +4195,50 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                }
        }
 
+       /* iDiag access PCI function control registers */
+       snprintf(name, sizeof(name), "ctlAcc");
+       if (!phba->idiag_ctl_acc) {
+               phba->idiag_ctl_acc =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                               phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
+               if (!phba->idiag_ctl_acc) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                        "2981 Can't create idiag debugfs\n");
+                       goto debug_failed;
+               }
+       }
+
+       /* iDiag access mbox commands */
+       snprintf(name, sizeof(name), "mbxAcc");
+       if (!phba->idiag_mbx_acc) {
+               phba->idiag_mbx_acc =
+                       debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+                               phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
+               if (!phba->idiag_mbx_acc) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                       "2980 Can't create idiag debugfs\n");
+                       goto debug_failed;
+               }
+       }
+
+       /* iDiag extents access commands */
+       if (phba->sli4_hba.extents_in_use) {
+               snprintf(name, sizeof(name), "extAcc");
+               if (!phba->idiag_ext_acc) {
+                       phba->idiag_ext_acc =
+                               debugfs_create_file(name,
+                                                   S_IFREG|S_IRUGO|S_IWUSR,
+                                                   phba->idiag_root, phba,
+                                                   &lpfc_idiag_op_extAcc);
+                       if (!phba->idiag_ext_acc) {
+                               lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                               "2986 Cant create "
+                                               "idiag debugfs\n");
+                               goto debug_failed;
+                       }
+               }
+       }
+
 debug_failed:
        return;
 #endif
@@ -2800,7 +4273,6 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                debugfs_remove(vport->debug_nodelist); /* nodelist */
                vport->debug_nodelist = NULL;
        }
-
        if (vport->vport_debugfs_root) {
                debugfs_remove(vport->vport_debugfs_root); /* vportX */
                vport->vport_debugfs_root = NULL;
@@ -2829,6 +4301,30 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                        debugfs_remove(phba->debug_dumpDif); /* dumpDif */
                        phba->debug_dumpDif = NULL;
                }
+               if (phba->debug_InjErrLBA) {
+                       debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
+                       phba->debug_InjErrLBA = NULL;
+               }
+               if (phba->debug_writeGuard) {
+                       debugfs_remove(phba->debug_writeGuard); /* writeGuard */
+                       phba->debug_writeGuard = NULL;
+               }
+               if (phba->debug_writeApp) {
+                       debugfs_remove(phba->debug_writeApp); /* writeApp */
+                       phba->debug_writeApp = NULL;
+               }
+               if (phba->debug_writeRef) {
+                       debugfs_remove(phba->debug_writeRef); /* writeRef */
+                       phba->debug_writeRef = NULL;
+               }
+               if (phba->debug_readApp) {
+                       debugfs_remove(phba->debug_readApp); /* readApp */
+                       phba->debug_readApp = NULL;
+               }
+               if (phba->debug_readRef) {
+                       debugfs_remove(phba->debug_readRef); /* readRef */
+                       phba->debug_readRef = NULL;
+               }
 
                if (phba->slow_ring_trc) {
                        kfree(phba->slow_ring_trc);
@@ -2844,6 +4340,21 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                 * iDiag release
                 */
                if (phba->sli_rev == LPFC_SLI_REV4) {
+                       if (phba->idiag_ext_acc) {
+                               /* iDiag extAcc */
+                               debugfs_remove(phba->idiag_ext_acc);
+                               phba->idiag_ext_acc = NULL;
+                       }
+                       if (phba->idiag_mbx_acc) {
+                               /* iDiag mbxAcc */
+                               debugfs_remove(phba->idiag_mbx_acc);
+                               phba->idiag_mbx_acc = NULL;
+                       }
+                       if (phba->idiag_ctl_acc) {
+                               /* iDiag ctlAcc */
+                               debugfs_remove(phba->idiag_ctl_acc);
+                               phba->idiag_ctl_acc = NULL;
+                       }
                        if (phba->idiag_drb_acc) {
                                /* iDiag drbAcc */
                                debugfs_remove(phba->idiag_drb_acc);
@@ -2859,6 +4370,11 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                                debugfs_remove(phba->idiag_que_info);
                                phba->idiag_que_info = NULL;
                        }
+                       if (phba->idiag_bar_acc) {
+                               /* iDiag barAcc */
+                               debugfs_remove(phba->idiag_bar_acc);
+                               phba->idiag_bar_acc = NULL;
+                       }
                        if (phba->idiag_pci_cfg) {
                                /* iDiag pciCfg */
                                debugfs_remove(phba->idiag_pci_cfg);
index 6525a5e62d27eac813514e23178e5e898d976f14..f83bd944edd86c29fbe82a45228e8149a63dad45 100644 (file)
 /* hbqinfo output buffer size */
 #define LPFC_HBQINFO_SIZE 8192
 
+/*
+ * For SLI4 iDiag debugfs diagnostics tool
+ */
+
 /* pciConf */
 #define LPFC_PCI_CFG_BROWSE 0xffff
 #define LPFC_PCI_CFG_RD_CMD_ARG 2
 #define LPFC_PCI_CFG_WR_CMD_ARG 3
 #define LPFC_PCI_CFG_SIZE 4096
-#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2)
 #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
 
+#define IDIAG_PCICFG_WHERE_INDX 0
+#define IDIAG_PCICFG_COUNT_INDX 1
+#define IDIAG_PCICFG_VALUE_INDX 2
+
+/* barAcc */
+#define LPFC_PCI_BAR_BROWSE 0xffff
+#define LPFC_PCI_BAR_RD_CMD_ARG 3
+#define LPFC_PCI_BAR_WR_CMD_ARG 3
+
+#define LPFC_PCI_IF0_BAR0_SIZE (1024 *  16)
+#define LPFC_PCI_IF0_BAR1_SIZE (1024 * 128)
+#define LPFC_PCI_IF0_BAR2_SIZE (1024 * 128)
+#define LPFC_PCI_IF2_BAR0_SIZE (1024 *  32)
+
+#define LPFC_PCI_BAR_RD_BUF_SIZE 4096
+#define LPFC_PCI_BAR_RD_SIZE (LPFC_PCI_BAR_RD_BUF_SIZE/4)
+
+#define LPFC_PCI_IF0_BAR0_RD_SIZE (LPFC_PCI_IF0_BAR0_SIZE/4)
+#define LPFC_PCI_IF0_BAR1_RD_SIZE (LPFC_PCI_IF0_BAR1_SIZE/4)
+#define LPFC_PCI_IF0_BAR2_RD_SIZE (LPFC_PCI_IF0_BAR2_SIZE/4)
+#define LPFC_PCI_IF2_BAR0_RD_SIZE (LPFC_PCI_IF2_BAR0_SIZE/4)
+
+#define IDIAG_BARACC_BAR_NUM_INDX 0
+#define IDIAG_BARACC_OFF_SET_INDX 1
+#define IDIAG_BARACC_ACC_MOD_INDX 2
+#define IDIAG_BARACC_REG_VAL_INDX 2
+#define IDIAG_BARACC_BAR_SZE_INDX 3
+
+#define IDIAG_BARACC_BAR_0 0
+#define IDIAG_BARACC_BAR_1 1
+#define IDIAG_BARACC_BAR_2 2
+
+#define SINGLE_WORD 1
+
 /* queue info */
 #define LPFC_QUE_INFO_GET_BUF_SIZE 4096
 
 #define LPFC_IDIAG_WQ 4
 #define LPFC_IDIAG_RQ 5
 
-/* doorbell acc */
+#define IDIAG_QUEACC_QUETP_INDX 0
+#define IDIAG_QUEACC_QUEID_INDX 1
+#define IDIAG_QUEACC_INDEX_INDX 2
+#define IDIAG_QUEACC_COUNT_INDX 3
+#define IDIAG_QUEACC_OFFST_INDX 4
+#define IDIAG_QUEACC_VALUE_INDX 5
+
+/* doorbell register acc */
 #define LPFC_DRB_ACC_ALL 0xffff
 #define LPFC_DRB_ACC_RD_CMD_ARG 1
 #define LPFC_DRB_ACC_WR_CMD_ARG 2
 
 #define LPFC_DRB_MAX  4
 
+#define IDIAG_DRBACC_REGID_INDX 0
+#define IDIAG_DRBACC_VALUE_INDX 1
+
+/* control register acc */
+#define LPFC_CTL_ACC_ALL 0xffff
+#define LPFC_CTL_ACC_RD_CMD_ARG 1
+#define LPFC_CTL_ACC_WR_CMD_ARG 2
+#define LPFC_CTL_ACC_BUF_SIZE 256
+
+#define LPFC_CTL_PORT_SEM  1
+#define LPFC_CTL_PORT_STA  2
+#define LPFC_CTL_PORT_CTL  3
+#define LPFC_CTL_PORT_ER1  4
+#define LPFC_CTL_PORT_ER2  5
+#define LPFC_CTL_PDEV_CTL  6
+
+#define LPFC_CTL_MAX  6
+
+#define IDIAG_CTLACC_REGID_INDX 0
+#define IDIAG_CTLACC_VALUE_INDX 1
+
+/* mailbox access */
+#define LPFC_MBX_DMP_ARG 4
+
+#define LPFC_MBX_ACC_BUF_SIZE 512
+#define LPFC_MBX_ACC_LBUF_SZ 128
+
+#define LPFC_MBX_DMP_MBX_WORD 0x00000001
+#define LPFC_MBX_DMP_MBX_BYTE 0x00000002
+#define LPFC_MBX_DMP_MBX_ALL (LPFC_MBX_DMP_MBX_WORD | LPFC_MBX_DMP_MBX_BYTE)
+
+#define LPFC_BSG_DMP_MBX_RD_MBX 0x00000001
+#define LPFC_BSG_DMP_MBX_RD_BUF 0x00000002
+#define LPFC_BSG_DMP_MBX_WR_MBX 0x00000004
+#define LPFC_BSG_DMP_MBX_WR_BUF 0x00000008
+#define LPFC_BSG_DMP_MBX_ALL (LPFC_BSG_DMP_MBX_RD_MBX | \
+                             LPFC_BSG_DMP_MBX_RD_BUF | \
+                             LPFC_BSG_DMP_MBX_WR_MBX | \
+                             LPFC_BSG_DMP_MBX_WR_BUF)
+
+#define LPFC_MBX_DMP_ALL 0xffff
+#define LPFC_MBX_ALL_CMD 0xff
+
+#define IDIAG_MBXACC_MBCMD_INDX 0
+#define IDIAG_MBXACC_DPMAP_INDX 1
+#define IDIAG_MBXACC_DPCNT_INDX 2
+#define IDIAG_MBXACC_WDCNT_INDX 3
+
+/* extents access */
+#define LPFC_EXT_ACC_CMD_ARG 1
+#define LPFC_EXT_ACC_BUF_SIZE 4096
+
+#define LPFC_EXT_ACC_AVAIL 0x1
+#define LPFC_EXT_ACC_ALLOC 0x2
+#define LPFC_EXT_ACC_DRIVR 0x4
+#define LPFC_EXT_ACC_ALL   (LPFC_EXT_ACC_DRIVR | \
+                           LPFC_EXT_ACC_AVAIL | \
+                           LPFC_EXT_ACC_ALLOC)
+
+#define IDIAG_EXTACC_EXMAP_INDX 0
+
 #define SIZE_U8  sizeof(uint8_t)
 #define SIZE_U16 sizeof(uint16_t)
 #define SIZE_U32 sizeof(uint32_t)
@@ -110,6 +215,11 @@ struct lpfc_idiag_cmd {
 #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
 #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
 
+#define LPFC_IDIAG_CMD_BARACC_RD 0x00000008
+#define LPFC_IDIAG_CMD_BARACC_WR 0x00000009
+#define LPFC_IDIAG_CMD_BARACC_ST 0x0000000a
+#define LPFC_IDIAG_CMD_BARACC_CL 0x0000000b
+
 #define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011
 #define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012
 #define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013
@@ -119,6 +229,17 @@ struct lpfc_idiag_cmd {
 #define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022
 #define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023
 #define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024
+
+#define LPFC_IDIAG_CMD_CTLACC_RD 0x00000031
+#define LPFC_IDIAG_CMD_CTLACC_WR 0x00000032
+#define LPFC_IDIAG_CMD_CTLACC_ST 0x00000033
+#define LPFC_IDIAG_CMD_CTLACC_CL 0x00000034
+
+#define LPFC_IDIAG_CMD_MBXACC_DP 0x00000041
+#define LPFC_IDIAG_BSG_MBXACC_DP 0x00000042
+
+#define LPFC_IDIAG_CMD_EXTACC_RD 0x00000051
+
        uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
 };
 
index 1d84b63fccadf49eb9f39374ef3b7d1b163d2d8c..a2af8543ee1b6b1d85b4931c0ca35bd4febbb473 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2008 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
index 1725b81770e92b5a99fe24afa7661082f3cf68d2..7afc757338de2de3137ed2643e5c4a1ac8701af1 100644 (file)
@@ -421,13 +421,13 @@ fail:
  * @vport: pointer to a host virtual N_Port data structure.
  *
  * This routine issues a REG_VFI mailbox for the vfi, vpi, fcfi triplet for
- * the @vport. This mailbox command is necessary for FCoE only.
+ * the @vport. This mailbox command is necessary for SLI4 port only.
  *
  * Return code
  *   0 - successfully issued REG_VFI for @vport
  *   A failure code otherwise.
  **/
-static int
+int
 lpfc_issue_reg_vfi(struct lpfc_vport *vport)
 {
        struct lpfc_hba  *phba = vport->phba;
@@ -438,10 +438,14 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport)
        int rc = 0;
 
        sp = &phba->fc_fabparam;
-       ndlp = lpfc_findnode_did(vport, Fabric_DID);
-       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
-               rc = -ENODEV;
-               goto fail;
+       /* move forward in case of SLI4 FC port loopback test */
+       if ((phba->sli_rev == LPFC_SLI_REV4) &&
+           !(phba->link_flag & LS_LOOPBACK_MODE)) {
+               ndlp = lpfc_findnode_did(vport, Fabric_DID);
+               if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+                       rc = -ENODEV;
+                       goto fail;
+               }
        }
 
        dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
@@ -486,6 +490,54 @@ fail:
        return rc;
 }
 
+/**
+ * lpfc_issue_unreg_vfi - Unregister VFI for this vport's fabric login
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This routine issues a UNREG_VFI mailbox with the vfi, vpi, fcfi triplet for
+ * the @vport. This mailbox command is necessary for SLI4 port only.
+ *
+ * Return code
+ *   0 - successfully issued REG_VFI for @vport
+ *   A failure code otherwise.
+ **/
+int
+lpfc_issue_unreg_vfi(struct lpfc_vport *vport)
+{
+       struct lpfc_hba *phba = vport->phba;
+       struct Scsi_Host *shost;
+       LPFC_MBOXQ_t *mboxq;
+       int rc;
+
+       mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mboxq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+                               "2556 UNREG_VFI mbox allocation failed"
+                               "HBA state x%x\n", phba->pport->port_state);
+               return -ENOMEM;
+       }
+
+       lpfc_unreg_vfi(mboxq, vport);
+       mboxq->vport = vport;
+       mboxq->mbox_cmpl = lpfc_unregister_vfi_cmpl;
+
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
+       if (rc == MBX_NOT_FINISHED) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+                               "2557 UNREG_VFI issue mbox failed rc x%x "
+                               "HBA state x%x\n",
+                               rc, phba->pport->port_state);
+               mempool_free(mboxq, phba->mbox_mem_pool);
+               return -EIO;
+       }
+
+       shost = lpfc_shost_from_vport(vport);
+       spin_lock_irq(shost->host_lock);
+       vport->fc_flag &= ~FC_VFI_REGISTERED;
+       spin_unlock_irq(shost->host_lock);
+       return 0;
+}
+
 /**
  * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean.
  * @vport: pointer to a host virtual N_Port data structure.
@@ -615,7 +667,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                                         "1816 FLOGI NPIV supported, "
                                         "response data 0x%x\n",
                                         sp->cmn.response_multiple_NPort);
+                       spin_lock_irq(&phba->hbalock);
                        phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
+                       spin_unlock_irq(&phba->hbalock);
                } else {
                        /* Because we asked f/w for NPIV it still expects us
                        to call reg_vnpid atleast for the physcial host */
@@ -623,7 +677,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                                         LOG_ELS | LOG_VPORT,
                                         "1817 Fabric does not support NPIV "
                                         "- configuring single port mode.\n");
+                       spin_lock_irq(&phba->hbalock);
                        phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
+                       spin_unlock_irq(&phba->hbalock);
                }
        }
 
@@ -686,11 +742,16 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        lpfc_do_scr_ns_plogi(phba, vport);
                } else if (vport->fc_flag & FC_VFI_REGISTERED)
                        lpfc_issue_init_vpi(vport);
-               else
+               else {
+                       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                       "3135 Need register VFI: (x%x/%x)\n",
+                                       vport->fc_prevDID, vport->fc_myDID);
                        lpfc_issue_reg_vfi(vport);
+               }
        }
        return 0;
 }
+
 /**
  * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port
  * @vport: pointer to a host virtual N_Port data structure.
@@ -874,6 +935,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                        phba->fcf.current_rec.fcf_indx,
                                        irsp->ulpStatus, irsp->un.ulpWord[4],
                                        irsp->ulpTimeout);
+                       lpfc_sli4_set_fcf_flogi_fail(phba,
+                                       phba->fcf.current_rec.fcf_indx);
                        fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba);
                        rc = lpfc_sli4_fcf_rr_next_proc(vport, fcf_index);
                        if (rc)
@@ -905,17 +968,16 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
                 * alpa map would take too long otherwise.
                 */
-               if (phba->alpa_map[0] == 0) {
+               if (phba->alpa_map[0] == 0)
                        vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
-                       if ((phba->sli_rev == LPFC_SLI_REV4) &&
-                           (!(vport->fc_flag & FC_VFI_REGISTERED) ||
-                            (vport->fc_prevDID != vport->fc_myDID))) {
-                               if (vport->fc_flag & FC_VFI_REGISTERED)
-                                       lpfc_sli4_unreg_all_rpis(vport);
-                               lpfc_issue_reg_vfi(vport);
-                               lpfc_nlp_put(ndlp);
-                               goto out;
-                       }
+               if ((phba->sli_rev == LPFC_SLI_REV4) &&
+                   (!(vport->fc_flag & FC_VFI_REGISTERED) ||
+                    (vport->fc_prevDID != vport->fc_myDID))) {
+                       if (vport->fc_flag & FC_VFI_REGISTERED)
+                               lpfc_sli4_unreg_all_rpis(vport);
+                       lpfc_issue_reg_vfi(vport);
+                       lpfc_nlp_put(ndlp);
+                       goto out;
                }
                goto flogifail;
        }
@@ -1073,6 +1135,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        /* Setup CSPs accordingly for Fabric */
        sp->cmn.e_d_tov = 0;
        sp->cmn.w2.r_a_tov = 0;
+       sp->cmn.virtual_fabric_support = 0;
        sp->cls1.classValid = 0;
        sp->cls2.seqDelivery = 1;
        sp->cls3.seqDelivery = 1;
@@ -1161,8 +1224,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
        spin_lock_irq(&phba->hbalock);
        list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
                icmd = &iocb->iocb;
-               if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
-                   icmd->un.elsreq64.bdl.ulpIoTag32) {
+               if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
                        ndlp = (struct lpfc_nodelist *)(iocb->context1);
                        if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
                            (ndlp->nlp_DID == Fabric_DID))
@@ -3064,17 +3126,22 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        if (did == FDMI_DID)
                retry = 1;
 
-       if (((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) &&
+       if ((cmd == ELS_CMD_FLOGI) &&
            (phba->fc_topology != LPFC_TOPOLOGY_LOOP) &&
            !lpfc_error_lost_link(irsp)) {
                /* FLOGI retry policy */
                retry = 1;
-               /* retry forever */
+               /* retry FLOGI forever */
                maxretry = 0;
                if (cmdiocb->retry >= 100)
                        delay = 5000;
                else if (cmdiocb->retry >= 32)
                        delay = 1000;
+       } else if ((cmd == ELS_CMD_FDISC) && !lpfc_error_lost_link(irsp)) {
+               /* retry FDISCs every second up to devloss */
+               retry = 1;
+               maxretry = vport->cfg_devloss_tmo;
+               delay = 1000;
        }
 
        cmdiocb->retry++;
@@ -3384,7 +3451,20 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        cmdiocb->context1 = NULL;
                }
        }
+
+       /*
+        * The driver received a LOGO from the rport and has ACK'd it.
+        * At this point, the driver is done so release the IOCB
+        */
        lpfc_els_free_iocb(phba, cmdiocb);
+
+       /*
+        * Remove the ndlp reference if it's a fabric node that has
+        * sent us an unsolicted LOGO.
+        */
+       if (ndlp->nlp_type & NLP_FABRIC)
+               lpfc_nlp_put(ndlp);
+
        return;
 }
 
@@ -4080,9 +4160,6 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
 
        phba->fc_stat.elsXmitACC++;
        elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-       lpfc_nlp_put(ndlp);
-       elsiocb->context1 = NULL;  /* Don't need ndlp for cmpl,
-                                   * it could be freed */
 
        rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
        if (rc == IOCB_ERROR) {
@@ -4164,6 +4241,11 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
        psli = &phba->sli;
        cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len;
 
+       /* The accumulated length can exceed the BPL_SIZE.  For
+        * now, use this as the limit
+        */
+       if (cmdsize > LPFC_BPL_SIZE)
+               cmdsize = LPFC_BPL_SIZE;
        elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
                                     ndlp->nlp_DID, ELS_CMD_ACC);
        if (!elsiocb)
@@ -4187,9 +4269,6 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
 
        phba->fc_stat.elsXmitACC++;
        elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-       lpfc_nlp_put(ndlp);
-       elsiocb->context1 = NULL;  /* Don't need ndlp for cmpl,
-                                   * it could be freed */
 
        rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
        if (rc == IOCB_ERROR) {
@@ -4859,23 +4938,31 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                            sizeof(struct lpfc_name));
 
                if (!rc) {
-                       mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-                       if (!mbox)
+                       if (phba->sli_rev < LPFC_SLI_REV4) {
+                               mbox = mempool_alloc(phba->mbox_mem_pool,
+                                                    GFP_KERNEL);
+                               if (!mbox)
+                                       return 1;
+                               lpfc_linkdown(phba);
+                               lpfc_init_link(phba, mbox,
+                                              phba->cfg_topology,
+                                              phba->cfg_link_speed);
+                               mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0;
+                               mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+                               mbox->vport = vport;
+                               rc = lpfc_sli_issue_mbox(phba, mbox,
+                                                        MBX_NOWAIT);
+                               lpfc_set_loopback_flag(phba);
+                               if (rc == MBX_NOT_FINISHED)
+                                       mempool_free(mbox, phba->mbox_mem_pool);
                                return 1;
-
-                       lpfc_linkdown(phba);
-                       lpfc_init_link(phba, mbox,
-                                      phba->cfg_topology,
-                                      phba->cfg_link_speed);
-                       mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0;
-                       mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-                       mbox->vport = vport;
-                       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
-                       lpfc_set_loopback_flag(phba);
-                       if (rc == MBX_NOT_FINISHED) {
-                               mempool_free(mbox, phba->mbox_mem_pool);
+                       } else {
+                               /* abort the flogi coming back to ourselves
+                                * due to external loopback on the port.
+                                */
+                               lpfc_els_abort_flogi(phba);
+                               return 0;
                        }
-                       return 1;
                } else if (rc > 0) {    /* greater than */
                        spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_PT2PT_PLOGI;
@@ -5830,8 +5917,12 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        vport->fc_myDID = vport->fc_prevDID;
                        if (phba->sli_rev < LPFC_SLI_REV4)
                                lpfc_issue_fabric_reglogin(vport);
-                       else
+                       else {
+                               lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                       "3138 Need register VFI: (x%x/%x)\n",
+                                       vport->fc_prevDID, vport->fc_myDID);
                                lpfc_issue_reg_vfi(vport);
+                       }
                }
        }
        return 0;
@@ -6587,56 +6678,6 @@ dropit:
        phba->fc_stat.elsRcvDrop++;
 }
 
-/**
- * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier
- * @phba: pointer to lpfc hba data structure.
- * @vpi: host virtual N_Port identifier.
- *
- * This routine finds a vport on a HBA (referred by @phba) through a
- * @vpi. The function walks the HBA's vport list and returns the address
- * of the vport with the matching @vpi.
- *
- * Return code
- *    NULL - No vport with the matching @vpi found
- *    Otherwise - Address to the vport with the matching @vpi.
- **/
-struct lpfc_vport *
-lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
-{
-       struct lpfc_vport *vport;
-       unsigned long flags;
-       int i = 0;
-
-       /* The physical ports are always vpi 0 - translate is unnecessary. */
-       if (vpi > 0) {
-               /*
-                * Translate the physical vpi to the logical vpi.  The
-                * vport stores the logical vpi.
-                */
-               for (i = 0; i < phba->max_vpi; i++) {
-                       if (vpi == phba->vpi_ids[i])
-                               break;
-               }
-
-               if (i >= phba->max_vpi) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-                                        "2936 Could not find Vport mapped "
-                                        "to vpi %d\n", vpi);
-                       return NULL;
-               }
-       }
-
-       spin_lock_irqsave(&phba->hbalock, flags);
-       list_for_each_entry(vport, &phba->port_list, listentry) {
-               if (vport->vpi == i) {
-                       spin_unlock_irqrestore(&phba->hbalock, flags);
-                       return vport;
-               }
-       }
-       spin_unlock_irqrestore(&phba->hbalock, flags);
-       return NULL;
-}
-
 /**
  * lpfc_els_unsol_event - Process an unsolicited event from an els sli ring
  * @phba: pointer to lpfc hba data structure.
@@ -7256,16 +7297,11 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        icmd->un.elsreq64.myID = 0;
        icmd->un.elsreq64.fl = 1;
 
-       if  ((phba->sli_rev == LPFC_SLI_REV4) &&
-            (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
-             LPFC_SLI_INTF_IF_TYPE_0)) {
-               /* FDISC needs to be 1 for WQE VPI */
-               elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1;
-               elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ;
-               /* Set the ulpContext to the vpi */
-               elsiocb->iocb.ulpContext = phba->vpi_ids[vport->vpi];
-       } else {
-               /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
+       /*
+        * SLI3 ports require a different context type value than SLI4.
+        * Catch SLI3 ports here and override the prep.
+        */
+       if (phba->sli_rev == LPFC_SLI_REV3) {
                icmd->ulpCt_h = 1;
                icmd->ulpCt_l = 0;
        }
@@ -7278,6 +7314,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        /* Setup CSPs accordingly for Fabric */
        sp->cmn.e_d_tov = 0;
        sp->cmn.w2.r_a_tov = 0;
+       sp->cmn.virtual_fabric_support = 0;
        sp->cls1.classValid = 0;
        sp->cls2.seqDelivery = 1;
        sp->cls3.seqDelivery = 1;
index d9f1908a17f70a5e854f07a0f60e8468e460bf21..678a4b11059c3ad7feccadf7a8428d6436a3e218 100644 (file)
@@ -1074,6 +1074,12 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 
        mempool_free(pmb, phba->mbox_mem_pool);
 
+       /* don't perform discovery for SLI4 loopback diagnostic test */
+       if ((phba->sli_rev == LPFC_SLI_REV4) &&
+           !(phba->hba_flag & HBA_FCOE_MODE) &&
+           (phba->link_flag & LS_LOOPBACK_MODE))
+               return;
+
        if (phba->fc_topology == LPFC_TOPOLOGY_LOOP &&
            vport->fc_flag & FC_PUBLIC_LOOP &&
            !(vport->fc_flag & FC_LBIT)) {
@@ -1109,6 +1115,28 @@ out:
        return;
 }
 
+/**
+ * lpfc_sli4_clear_fcf_rr_bmask
+ * @phba pointer to the struct lpfc_hba for this port.
+ * This fucnction resets the round robin bit mask and clears the
+ * fcf priority list. The list deletions are done while holding the
+ * hbalock. The ON_LIST flag and the FLOGI_FAILED flags are cleared
+ * from the lpfc_fcf_pri record.
+ **/
+void
+lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *phba)
+{
+       struct lpfc_fcf_pri *fcf_pri;
+       struct lpfc_fcf_pri *next_fcf_pri;
+       memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask));
+       spin_lock_irq(&phba->hbalock);
+       list_for_each_entry_safe(fcf_pri, next_fcf_pri,
+                               &phba->fcf.fcf_pri_list, list) {
+               list_del_init(&fcf_pri->list);
+               fcf_pri->fcf_rec.flag = 0;
+       }
+       spin_unlock_irq(&phba->hbalock);
+}
 static void
 lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
@@ -1130,7 +1158,8 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        spin_unlock_irq(&phba->hbalock);
 
        /* If there is a pending FCoE event, restart FCF table scan. */
-       if (lpfc_check_pending_fcoe_event(phba, LPFC_UNREG_FCF))
+       if ((!(phba->hba_flag & FCF_RR_INPROG)) &&
+               lpfc_check_pending_fcoe_event(phba, LPFC_UNREG_FCF))
                goto fail_out;
 
        /* Mark successful completion of FCF table scan */
@@ -1249,6 +1278,30 @@ lpfc_vlan_id_match(uint16_t curr_vlan_id, uint16_t new_vlan_id)
        return (curr_vlan_id == new_vlan_id);
 }
 
+/**
+ * lpfc_update_fcf_record - Update driver fcf record
+ * __lpfc_update_fcf_record_pri - update the lpfc_fcf_pri record.
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index: Index for the lpfc_fcf_record.
+ * @new_fcf_record: pointer to hba fcf record.
+ *
+ * This routine updates the driver FCF priority record from the new HBA FCF
+ * record. This routine is called with the host lock held.
+ **/
+static void
+__lpfc_update_fcf_record_pri(struct lpfc_hba *phba, uint16_t fcf_index,
+                                struct fcf_record *new_fcf_record
+                                )
+{
+       struct lpfc_fcf_pri *fcf_pri;
+
+       fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       fcf_pri->fcf_rec.fcf_index = fcf_index;
+       /* FCF record priority */
+       fcf_pri->fcf_rec.priority = new_fcf_record->fip_priority;
+
+}
+
 /**
  * lpfc_copy_fcf_record - Copy fcf information to lpfc_hba.
  * @fcf: pointer to driver fcf record.
@@ -1332,6 +1385,9 @@ __lpfc_update_fcf_record(struct lpfc_hba *phba, struct lpfc_fcf_rec *fcf_rec,
        fcf_rec->addr_mode = addr_mode;
        fcf_rec->vlan_id = vlan_id;
        fcf_rec->flag |= (flag | RECORD_VALID);
+       __lpfc_update_fcf_record_pri(phba,
+               bf_get(lpfc_fcf_record_fcf_index, new_fcf_record),
+                                new_fcf_record);
 }
 
 /**
@@ -1362,7 +1418,7 @@ lpfc_register_fcf(struct lpfc_hba *phba)
                if (phba->pport->port_state != LPFC_FLOGI) {
                        phba->hba_flag |= FCF_RR_INPROG;
                        spin_unlock_irq(&phba->hbalock);
-                       lpfc_issue_init_vfi(phba->pport);
+                       lpfc_initial_flogi(phba->pport);
                        return;
                }
                spin_unlock_irq(&phba->hbalock);
@@ -1834,6 +1890,8 @@ lpfc_sli4_fcf_record_match(struct lpfc_hba *phba,
                return false;
        if (!lpfc_fab_name_match(fcf_rec->fabric_name, new_fcf_record))
                return false;
+       if (fcf_rec->priority != new_fcf_record->fip_priority)
+               return false;
        return true;
 }
 
@@ -1896,6 +1954,152 @@ stop_flogi_current_fcf:
        return 1;
 }
 
+/**
+ * lpfc_sli4_fcf_pri_list_del
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to delete
+ * This routine checks the on list flag of the fcf_index to be deleted.
+ * If it is one the list then it is removed from the list, and the flag
+ * is cleared. This routine grab the hbalock before removing the fcf
+ * record from the list.
+ **/
+static void lpfc_sli4_fcf_pri_list_del(struct lpfc_hba *phba,
+                       uint16_t fcf_index)
+{
+       struct lpfc_fcf_pri *new_fcf_pri;
+
+       new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+               "3058 deleting idx x%x pri x%x flg x%x\n",
+               fcf_index, new_fcf_pri->fcf_rec.priority,
+                new_fcf_pri->fcf_rec.flag);
+       spin_lock_irq(&phba->hbalock);
+       if (new_fcf_pri->fcf_rec.flag & LPFC_FCF_ON_PRI_LIST) {
+               if (phba->fcf.current_rec.priority ==
+                               new_fcf_pri->fcf_rec.priority)
+                       phba->fcf.eligible_fcf_cnt--;
+               list_del_init(&new_fcf_pri->list);
+               new_fcf_pri->fcf_rec.flag &= ~LPFC_FCF_ON_PRI_LIST;
+       }
+       spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_set_fcf_flogi_fail
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to update
+ * This routine acquires the hbalock and then set the LPFC_FCF_FLOGI_FAILED
+ * flag so the the round robin slection for the particular priority level
+ * will try a different fcf record that does not have this bit set.
+ * If the fcf record is re-read for any reason this flag is cleared brfore
+ * adding it to the priority list.
+ **/
+void
+lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *phba, uint16_t fcf_index)
+{
+       struct lpfc_fcf_pri *new_fcf_pri;
+       new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       spin_lock_irq(&phba->hbalock);
+       new_fcf_pri->fcf_rec.flag |= LPFC_FCF_FLOGI_FAILED;
+       spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_fcf_pri_list_add
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_index the index of the fcf record to add
+ * This routine checks the priority of the fcf_index to be added.
+ * If it is a lower priority than the current head of the fcf_pri list
+ * then it is added to the list in the right order.
+ * If it is the same priority as the current head of the list then it
+ * is added to the head of the list and its bit in the rr_bmask is set.
+ * If the fcf_index to be added is of a higher priority than the current
+ * head of the list then the rr_bmask is cleared, its bit is set in the
+ * rr_bmask and it is added to the head of the list.
+ * returns:
+ * 0=success 1=failure
+ **/
+int lpfc_sli4_fcf_pri_list_add(struct lpfc_hba *phba, uint16_t fcf_index,
+       struct fcf_record *new_fcf_record)
+{
+       uint16_t current_fcf_pri;
+       uint16_t last_index;
+       struct lpfc_fcf_pri *fcf_pri;
+       struct lpfc_fcf_pri *next_fcf_pri;
+       struct lpfc_fcf_pri *new_fcf_pri;
+       int ret;
+
+       new_fcf_pri = &phba->fcf.fcf_pri[fcf_index];
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+               "3059 adding idx x%x pri x%x flg x%x\n",
+               fcf_index, new_fcf_record->fip_priority,
+                new_fcf_pri->fcf_rec.flag);
+       spin_lock_irq(&phba->hbalock);
+       if (new_fcf_pri->fcf_rec.flag & LPFC_FCF_ON_PRI_LIST)
+               list_del_init(&new_fcf_pri->list);
+       new_fcf_pri->fcf_rec.fcf_index = fcf_index;
+       new_fcf_pri->fcf_rec.priority = new_fcf_record->fip_priority;
+       if (list_empty(&phba->fcf.fcf_pri_list)) {
+               list_add(&new_fcf_pri->list, &phba->fcf.fcf_pri_list);
+               ret = lpfc_sli4_fcf_rr_index_set(phba,
+                               new_fcf_pri->fcf_rec.fcf_index);
+               goto out;
+       }
+
+       last_index = find_first_bit(phba->fcf.fcf_rr_bmask,
+                               LPFC_SLI4_FCF_TBL_INDX_MAX);
+       if (last_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+               ret = 0; /* Empty rr list */
+               goto out;
+       }
+       current_fcf_pri = phba->fcf.fcf_pri[last_index].fcf_rec.priority;
+       if (new_fcf_pri->fcf_rec.priority <=  current_fcf_pri) {
+               list_add(&new_fcf_pri->list, &phba->fcf.fcf_pri_list);
+               if (new_fcf_pri->fcf_rec.priority <  current_fcf_pri) {
+                       memset(phba->fcf.fcf_rr_bmask, 0,
+                               sizeof(*phba->fcf.fcf_rr_bmask));
+                       /* fcfs_at_this_priority_level = 1; */
+                       phba->fcf.eligible_fcf_cnt = 1;
+               } else
+                       /* fcfs_at_this_priority_level++; */
+                       phba->fcf.eligible_fcf_cnt++;
+               ret = lpfc_sli4_fcf_rr_index_set(phba,
+                               new_fcf_pri->fcf_rec.fcf_index);
+               goto out;
+       }
+
+       list_for_each_entry_safe(fcf_pri, next_fcf_pri,
+                               &phba->fcf.fcf_pri_list, list) {
+               if (new_fcf_pri->fcf_rec.priority <=
+                               fcf_pri->fcf_rec.priority) {
+                       if (fcf_pri->list.prev == &phba->fcf.fcf_pri_list)
+                               list_add(&new_fcf_pri->list,
+                                               &phba->fcf.fcf_pri_list);
+                       else
+                               list_add(&new_fcf_pri->list,
+                                        &((struct lpfc_fcf_pri *)
+                                       fcf_pri->list.prev)->list);
+                       ret = 0;
+                       goto out;
+               } else if (fcf_pri->list.next == &phba->fcf.fcf_pri_list
+                       || new_fcf_pri->fcf_rec.priority <
+                               next_fcf_pri->fcf_rec.priority) {
+                       list_add(&new_fcf_pri->list, &fcf_pri->list);
+                       ret = 0;
+                       goto out;
+               }
+               if (new_fcf_pri->fcf_rec.priority > fcf_pri->fcf_rec.priority)
+                       continue;
+
+       }
+       ret = 1;
+out:
+       /* we use = instead of |= to clear the FLOGI_FAILED flag. */
+       new_fcf_pri->fcf_rec.flag = LPFC_FCF_ON_PRI_LIST;
+       spin_unlock_irq(&phba->hbalock);
+       return ret;
+}
+
 /**
  * lpfc_mbx_cmpl_fcf_scan_read_fcf_rec - fcf scan read_fcf mbox cmpl handler.
  * @phba: pointer to lpfc hba data structure.
@@ -1958,6 +2162,9 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
         * record for roundrobin FCF failover.
         */
        if (!rc) {
+               lpfc_sli4_fcf_pri_list_del(phba,
+                                       bf_get(lpfc_fcf_record_fcf_index,
+                                              new_fcf_record));
                lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
                                "2781 FCF (x%x) failed connection "
                                "list check: (x%x/x%x)\n",
@@ -1996,6 +2203,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                                spin_lock_irq(&phba->hbalock);
                                phba->fcf.fcf_flag |= FCF_REDISC_FOV;
                                spin_unlock_irq(&phba->hbalock);
+                               lpfc_sli4_mbox_cmd_free(phba, mboxq);
                                lpfc_sli4_fcf_scan_read_fcf_rec(phba,
                                                LPFC_FCOE_FCF_GET_FIRST);
                                return;
@@ -2004,7 +2212,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                goto read_next_fcf;
        } else {
                fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record);
-               rc = lpfc_sli4_fcf_rr_index_set(phba, fcf_index);
+               rc = lpfc_sli4_fcf_pri_list_add(phba, fcf_index,
+                                                       new_fcf_record);
                if (rc)
                        goto read_next_fcf;
        }
@@ -2017,7 +2226,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
         */
        spin_lock_irq(&phba->hbalock);
        if (phba->fcf.fcf_flag & FCF_IN_USE) {
-               if (lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec,
+               if (phba->cfg_fcf_failover_policy == LPFC_FCF_FOV &&
+                       lpfc_sli4_fcf_record_match(phba, &phba->fcf.current_rec,
                    new_fcf_record, vlan_id)) {
                        if (bf_get(lpfc_fcf_record_fcf_index, new_fcf_record) ==
                            phba->fcf.current_rec.fcf_indx) {
@@ -2231,7 +2441,8 @@ read_next_fcf:
                            (phba->fcf.fcf_flag & FCF_REDISC_PEND))
                                return;
 
-                       if (phba->fcf.fcf_flag & FCF_IN_USE) {
+                       if (phba->cfg_fcf_failover_policy == LPFC_FCF_FOV &&
+                               phba->fcf.fcf_flag & FCF_IN_USE) {
                                /*
                                 * In case the current in-use FCF record no
                                 * longer existed during FCF discovery that
@@ -2422,7 +2633,8 @@ lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 
        /* Update the eligible FCF record index bmask */
        fcf_index = bf_get(lpfc_fcf_record_fcf_index, new_fcf_record);
-       rc = lpfc_sli4_fcf_rr_index_set(phba, fcf_index);
+
+       rc = lpfc_sli4_fcf_pri_list_add(phba, fcf_index, new_fcf_record);
 
 out:
        lpfc_sli4_mbox_cmd_free(phba, mboxq);
@@ -2440,7 +2652,14 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
        struct lpfc_vport *vport = mboxq->vport;
 
-       if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) {
+       /*
+        * VFI not supported on interface type 0, just do the flogi
+        * Also continue if the VFI is in use - just use the same one.
+        */
+       if (mboxq->u.mb.mbxStatus &&
+           (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
+                       LPFC_SLI_INTF_IF_TYPE_0) &&
+           mboxq->u.mb.mbxStatus != MBX_VFI_IN_USE) {
                lpfc_printf_vlog(vport, KERN_ERR,
                                LOG_MBOX,
                                "2891 Init VFI mailbox failed 0x%x\n",
@@ -2449,6 +2668,7 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
                return;
        }
+
        lpfc_initial_flogi(vport);
        mempool_free(mboxq, phba->mbox_mem_pool);
        return;
@@ -2633,10 +2853,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                        lpfc_disc_list_loopmap(vport);
                        /* Start discovery */
                        lpfc_disc_start(vport);
-                       goto fail_free_mem;
+                       goto out_free_mem;
                }
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-               goto fail_free_mem;
+               goto out_free_mem;
        }
        /* The VPI is implicitly registered when the VFI is registered */
        spin_lock_irq(shost->host_lock);
@@ -2646,10 +2866,16 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI;
        spin_unlock_irq(shost->host_lock);
 
+       /* In case SLI4 FC loopback test, we are ready */
+       if ((phba->sli_rev == LPFC_SLI_REV4) &&
+           (phba->link_flag & LS_LOOPBACK_MODE)) {
+               phba->link_state = LPFC_HBA_READY;
+               goto out_free_mem;
+       }
+
        if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
                /* For private loop just start discovery and we are done. */
                if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
-                   (phba->alpa_map[0] == 0) &&
                    !(vport->fc_flag & FC_PUBLIC_LOOP)) {
                        /* Use loop map to make discovery list */
                        lpfc_disc_list_loopmap(vport);
@@ -2661,7 +2887,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                }
        }
 
-fail_free_mem:
+out_free_mem:
        mempool_free(mboxq, phba->mbox_mem_pool);
        lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
        kfree(dmabuf);
@@ -2714,6 +2940,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
 {
        struct lpfc_vport *vport = phba->pport;
        LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL;
+       struct Scsi_Host *shost;
        int i;
        struct lpfc_dmabuf *mp;
        int rc;
@@ -2737,6 +2964,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
        phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la);
        phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
 
+       shost = lpfc_shost_from_vport(vport);
        if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
                phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
 
@@ -2748,8 +2976,11 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                                "1309 Link Up Event npiv not supported in loop "
                                "topology\n");
                                /* Get Loop Map information */
-               if (bf_get(lpfc_mbx_read_top_il, la))
+               if (bf_get(lpfc_mbx_read_top_il, la)) {
+                       spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_LBIT;
+                       spin_unlock_irq(shost->host_lock);
+               }
 
                vport->fc_myDID = bf_get(lpfc_mbx_read_top_alpa_granted, la);
                i = la->lilpBde64.tus.f.bdeSize;
@@ -2794,11 +3025,13 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
        } else {
                if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
                        if (phba->max_vpi && phba->cfg_enable_npiv &&
-                          (phba->sli_rev == 3))
+                          (phba->sli_rev >= LPFC_SLI_REV3))
                                phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
                }
                vport->fc_myDID = phba->fc_pref_DID;
+               spin_lock_irq(shost->host_lock);
                vport->fc_flag |= FC_LBIT;
+               spin_unlock_irq(shost->host_lock);
        }
        spin_unlock_irq(&phba->hbalock);
 
@@ -2892,8 +3125,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                        goto out;
                }
                /* Reset FCF roundrobin bmask for new discovery */
-               memset(phba->fcf.fcf_rr_bmask, 0,
-                      sizeof(*phba->fcf.fcf_rr_bmask));
+               lpfc_sli4_clear_fcf_rr_bmask(phba);
        }
 
        return;
@@ -3016,15 +3248,14 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        } else if (bf_get(lpfc_mbx_read_top_att_type, la) ==
                   LPFC_ATT_LINK_DOWN) {
                phba->fc_stat.LinkDown++;
-               if (phba->link_flag & LS_LOOPBACK_MODE) {
+               if (phba->link_flag & LS_LOOPBACK_MODE)
                        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
                                "1308 Link Down Event in loop back mode "
                                "x%x received "
                                "Data: x%x x%x x%x\n",
                                la->eventTag, phba->fc_eventTag,
                                phba->pport->port_state, vport->fc_flag);
-               }
-               else {
+               else
                        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
                                "1305 Link Down Event x%x received "
                                "Data: x%x x%x x%x x%x x%x\n",
@@ -3032,7 +3263,6 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                phba->pport->port_state, vport->fc_flag,
                                bf_get(lpfc_mbx_read_top_mm, la),
                                bf_get(lpfc_mbx_read_top_fa, la));
-               }
                lpfc_mbx_issue_link_down(phba);
        }
        if ((bf_get(lpfc_mbx_read_top_mm, la)) &&
@@ -3386,6 +3616,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        MAILBOX_t *mb = &pmb->u.mb;
        struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
        struct lpfc_nodelist *ndlp;
+       struct Scsi_Host *shost;
 
        ndlp = (struct lpfc_nodelist *) pmb->context2;
        pmb->context1 = NULL;
@@ -3431,8 +3662,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                 * vport discovery */
                if (!(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG))
                        lpfc_start_fdiscs(phba);
-               else
+               else {
+                       shost = lpfc_shost_from_vport(vport);
+                       spin_lock_irq(shost->host_lock);
                        vport->fc_flag &= ~FC_LOGO_RCVD_DID_CHNG ;
+                       spin_unlock_irq(shost->host_lock);
+               }
                lpfc_do_scr_ns_plogi(phba, vport);
        }
 
@@ -5145,6 +5380,73 @@ lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn)
        return ndlp;
 }
 
+/*
+ * This routine looks up the ndlp lists for the given RPI. If the rpi
+ * is found, the routine returns the node element list pointer else
+ * return NULL.
+ */
+struct lpfc_nodelist *
+lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
+{
+       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_nodelist *ndlp;
+
+       spin_lock_irq(shost->host_lock);
+       ndlp = __lpfc_findnode_rpi(vport, rpi);
+       spin_unlock_irq(shost->host_lock);
+       return ndlp;
+}
+
+/**
+ * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier
+ * @phba: pointer to lpfc hba data structure.
+ * @vpi: the physical host virtual N_Port identifier.
+ *
+ * This routine finds a vport on a HBA (referred by @phba) through a
+ * @vpi. The function walks the HBA's vport list and returns the address
+ * of the vport with the matching @vpi.
+ *
+ * Return code
+ *    NULL - No vport with the matching @vpi found
+ *    Otherwise - Address to the vport with the matching @vpi.
+ **/
+struct lpfc_vport *
+lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
+{
+       struct lpfc_vport *vport;
+       unsigned long flags;
+       int i = 0;
+
+       /* The physical ports are always vpi 0 - translate is unnecessary. */
+       if (vpi > 0) {
+               /*
+                * Translate the physical vpi to the logical vpi.  The
+                * vport stores the logical vpi.
+                */
+               for (i = 0; i < phba->max_vpi; i++) {
+                       if (vpi == phba->vpi_ids[i])
+                               break;
+               }
+
+               if (i >= phba->max_vpi) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+                                        "2936 Could not find Vport mapped "
+                                        "to vpi %d\n", vpi);
+                       return NULL;
+               }
+       }
+
+       spin_lock_irqsave(&phba->hbalock, flags);
+       list_for_each_entry(vport, &phba->port_list, listentry) {
+               if (vport->vpi == i) {
+                       spin_unlock_irqrestore(&phba->hbalock, flags);
+                       return vport;
+               }
+       }
+       spin_unlock_irqrestore(&phba->hbalock, flags);
+       return NULL;
+}
+
 void
 lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
              uint32_t did)
@@ -5391,7 +5693,7 @@ out:
  *
  * This function frees memory associated with the mailbox command.
  */
-static void
+void
 lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
        struct lpfc_vport *vport = mboxq->vport;
@@ -5443,7 +5745,6 @@ lpfc_unregister_fcfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 int
 lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
 {
-       LPFC_MBOXQ_t *mbox;
        struct lpfc_vport **vports;
        struct lpfc_nodelist *ndlp;
        struct Scsi_Host *shost;
@@ -5479,35 +5780,9 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
 
-       /* Unregister VFI */
-       mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!mbox) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
-                               "2556 UNREG_VFI mbox allocation failed"
-                               "HBA state x%x\n", phba->pport->port_state);
-               return -ENOMEM;
-       }
-
-       lpfc_unreg_vfi(mbox, phba->pport);
-       mbox->vport = phba->pport;
-       mbox->mbox_cmpl = lpfc_unregister_vfi_cmpl;
-
-       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
-       if (rc == MBX_NOT_FINISHED) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
-                               "2557 UNREG_VFI issue mbox failed rc x%x "
-                               "HBA state x%x\n",
-                               rc, phba->pport->port_state);
-               mempool_free(mbox, phba->mbox_mem_pool);
-               return -EIO;
-       }
-
-       shost = lpfc_shost_from_vport(phba->pport);
-       spin_lock_irq(shost->host_lock);
-       phba->pport->fc_flag &= ~FC_VFI_REGISTERED;
-       spin_unlock_irq(shost->host_lock);
-
-       return 0;
+       /* Unregister the physical port VFI */
+       rc = lpfc_issue_unreg_vfi(phba->pport);
+       return rc;
 }
 
 /**
@@ -5591,7 +5866,7 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba)
        spin_unlock_irq(&phba->hbalock);
 
        /* Reset FCF roundrobin bmask for new discovery */
-       memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask));
+       lpfc_sli4_clear_fcf_rr_bmask(phba);
 
        rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST);
 
index df53d1075574f4d57603c804ba26396b26995b53..7245bead3755a03fd3e2f17a1d65034b1b98d348 100644 (file)
@@ -349,6 +349,12 @@ struct csp {
  * Word 1 Bit 31 in FLOGI response is clean address bit
  */
 #define clean_address_bit request_multiple_Nport /* Word 1, bit 31 */
+/*
+ * Word 1 Bit 30 in common service parameter is overloaded.
+ * Word 1 Bit 30 in FLOGI request is Virtual Fabrics
+ * Word 1 Bit 30 in PLOGI request is random offset
+ */
+#define virtual_fabric_support randomOffset /* Word 1, bit 30 */
 #ifdef __BIG_ENDIAN_BITFIELD
        uint16_t request_multiple_Nport:1;      /* FC Word 1, bit 31 */
        uint16_t randomOffset:1;        /* FC Word 1, bit 30 */
@@ -1852,8 +1858,8 @@ typedef struct {
        uint8_t fabric_AL_PA;   /* If using a Fabric Assigned AL_PA */
 #endif
 
-#define FLAGS_LOCAL_LB               0x01 /* link_flags (=1) ENDEC loopback */
 #define FLAGS_TOPOLOGY_MODE_LOOP_PT  0x00 /* Attempt loop then pt-pt */
+#define FLAGS_LOCAL_LB               0x01 /* link_flags (=1) ENDEC loopback */
 #define FLAGS_TOPOLOGY_MODE_PT_PT    0x02 /* Attempt pt-pt only */
 #define FLAGS_TOPOLOGY_MODE_LOOP     0x04 /* Attempt loop only */
 #define FLAGS_TOPOLOGY_MODE_PT_LOOP  0x06 /* Attempt pt-pt then loop */
@@ -2819,7 +2825,8 @@ typedef struct {
 #ifdef __BIG_ENDIAN_BITFIELD
        uint32_t rsvd1     : 19;  /* Reserved                             */
        uint32_t cdss      :  1;  /* Configure Data Security SLI          */
-       uint32_t rsvd2     :  3;  /* Reserved                             */
+       uint32_t casabt    :  1;  /* Configure async abts status notice   */
+       uint32_t rsvd2     :  2;  /* Reserved                             */
        uint32_t cbg       :  1;  /* Configure BlockGuard                 */
        uint32_t cmv       :  1;  /* Configure Max VPIs                   */
        uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
@@ -2839,14 +2846,16 @@ typedef struct {
        uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
        uint32_t cmv       :  1;  /* Configure Max VPIs                   */
        uint32_t cbg       :  1;  /* Configure BlockGuard                 */
-       uint32_t rsvd2     :  3;  /* Reserved                             */
+       uint32_t rsvd2     :  2;  /* Reserved                             */
+       uint32_t casabt    :  1;  /* Configure async abts status notice   */
        uint32_t cdss      :  1;  /* Configure Data Security SLI          */
        uint32_t rsvd1     : 19;  /* Reserved                             */
 #endif
 #ifdef __BIG_ENDIAN_BITFIELD
        uint32_t rsvd3     : 19;  /* Reserved                             */
        uint32_t gdss      :  1;  /* Configure Data Security SLI          */
-       uint32_t rsvd4     :  3;  /* Reserved                             */
+       uint32_t gasabt    :  1;  /* Grant async abts status notice       */
+       uint32_t rsvd4     :  2;  /* Reserved                             */
        uint32_t gbg       :  1;  /* Grant BlockGuard                     */
        uint32_t gmv       :  1;  /* Grant Max VPIs                       */
        uint32_t gcrp      :  1;  /* Grant Command Ring Polling           */
@@ -2866,7 +2875,8 @@ typedef struct {
        uint32_t gcrp      :  1;  /* Grant Command Ring Polling           */
        uint32_t gmv       :  1;  /* Grant Max VPIs                       */
        uint32_t gbg       :  1;  /* Grant BlockGuard                     */
-       uint32_t rsvd4     :  3;  /* Reserved                             */
+       uint32_t rsvd4     :  2;  /* Reserved                             */
+       uint32_t gasabt    :  1;  /* Grant async abts status notice       */
        uint32_t gdss      :  1;  /* Configure Data Security SLI          */
        uint32_t rsvd3     : 19;  /* Reserved                             */
 #endif
@@ -2955,18 +2965,18 @@ typedef struct _SLI2_RDSC {
 typedef struct _PCB {
 #ifdef __BIG_ENDIAN_BITFIELD
        uint32_t type:8;
-#define TYPE_NATIVE_SLI2       0x01;
+#define TYPE_NATIVE_SLI2       0x01
        uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2   0x01;
+#define FEATURE_INITIAL_SLI2   0x01
        uint32_t rsvd:12;
        uint32_t maxRing:4;
 #else  /*  __LITTLE_ENDIAN_BITFIELD */
        uint32_t maxRing:4;
        uint32_t rsvd:12;
        uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2   0x01;
+#define FEATURE_INITIAL_SLI2   0x01
        uint32_t type:8;
-#define TYPE_NATIVE_SLI2       0x01;
+#define TYPE_NATIVE_SLI2       0x01
 #endif
 
        uint32_t mailBoxSize;
@@ -3465,6 +3475,7 @@ typedef struct {
 } ASYNCSTAT_FIELDS;
 #define ASYNC_TEMP_WARN                0x100
 #define ASYNC_TEMP_SAFE                0x101
+#define ASYNC_STATUS_CN                0x102
 
 /* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7)
    or CMD_IOCB_RCV_SEQ64_CX (0xB5) */
index 7f8003b5181eb47504b86930550af227853ca2b1..ad3ab5005e1a071356c89471c55c083b856f89fe 100644 (file)
@@ -41,6 +41,8 @@
  * Or clear that bit field:
  *     bf_set(example_bit_field, &t1, 0);
  */
+#define bf_get_be32(name, ptr) \
+       ((be32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
 #define bf_get_le32(name, ptr) \
        ((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
 #define bf_get(name, ptr) \
@@ -678,7 +680,6 @@ struct lpfc_register {
 #define lpfc_rq_doorbell_num_posted_SHIFT      16
 #define lpfc_rq_doorbell_num_posted_MASK       0x3FFF
 #define lpfc_rq_doorbell_num_posted_WORD       word0
-#define LPFC_RQ_POST_BATCH             8       /* RQEs to post at one time */
 #define lpfc_rq_doorbell_id_SHIFT              0
 #define lpfc_rq_doorbell_id_MASK               0xFFFF
 #define lpfc_rq_doorbell_id_WORD               word0
@@ -784,6 +785,8 @@ union lpfc_sli4_cfg_shdr {
 #define LPFC_Q_CREATE_VERSION_2        2
 #define LPFC_Q_CREATE_VERSION_1        1
 #define LPFC_Q_CREATE_VERSION_0        0
+#define LPFC_OPCODE_VERSION_0  0
+#define LPFC_OPCODE_VERSION_1  1
        } request;
        struct {
                uint32_t word6;
@@ -825,6 +828,7 @@ struct mbox_header {
 #define LPFC_EXTENT_VERSION_DEFAULT    0
 
 /* Subsystem Definitions */
+#define LPFC_MBOX_SUBSYSTEM_NA         0x0
 #define LPFC_MBOX_SUBSYSTEM_COMMON     0x1
 #define LPFC_MBOX_SUBSYSTEM_FCOE       0xC
 
@@ -835,25 +839,34 @@ struct mbox_header {
 #define HOST_ENDIAN_HIGH_WORD1 0xFF7856FF
 
 /* Common Opcodes */
-#define LPFC_MBOX_OPCODE_CQ_CREATE             0x0C
-#define LPFC_MBOX_OPCODE_EQ_CREATE             0x0D
-#define LPFC_MBOX_OPCODE_MQ_CREATE             0x15
-#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES   0x20
-#define LPFC_MBOX_OPCODE_NOP                   0x21
-#define LPFC_MBOX_OPCODE_MQ_DESTROY            0x35
-#define LPFC_MBOX_OPCODE_CQ_DESTROY            0x36
-#define LPFC_MBOX_OPCODE_EQ_DESTROY            0x37
-#define LPFC_MBOX_OPCODE_QUERY_FW_CFG          0x3A
-#define LPFC_MBOX_OPCODE_FUNCTION_RESET                0x3D
-#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT         0x5A
-#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO  0x9A
-#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B
-#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT     0x9C
-#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT   0x9D
-#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG    0xA0
-#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG    0xA4
-#define LPFC_MBOX_OPCODE_WRITE_OBJECT          0xAC
-#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS   0xB5
+#define LPFC_MBOX_OPCODE_NA                            0x00
+#define LPFC_MBOX_OPCODE_CQ_CREATE                     0x0C
+#define LPFC_MBOX_OPCODE_EQ_CREATE                     0x0D
+#define LPFC_MBOX_OPCODE_MQ_CREATE                     0x15
+#define LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES           0x20
+#define LPFC_MBOX_OPCODE_NOP                           0x21
+#define LPFC_MBOX_OPCODE_MQ_DESTROY                    0x35
+#define LPFC_MBOX_OPCODE_CQ_DESTROY                    0x36
+#define LPFC_MBOX_OPCODE_EQ_DESTROY                    0x37
+#define LPFC_MBOX_OPCODE_QUERY_FW_CFG                  0x3A
+#define LPFC_MBOX_OPCODE_FUNCTION_RESET                        0x3D
+#define LPFC_MBOX_OPCODE_GET_PORT_NAME                 0x4D
+#define LPFC_MBOX_OPCODE_MQ_CREATE_EXT                 0x5A
+#define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO          0x9A
+#define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT         0x9B
+#define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT             0x9C
+#define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT           0x9D
+#define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG           0xA0
+#define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG            0xA4
+#define LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG            0xA5
+#define LPFC_MBOX_OPCODE_GET_PROFILE_LIST              0xA6
+#define LPFC_MBOX_OPCODE_SET_ACT_PROFILE               0xA8
+#define LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG    0xA9
+#define LPFC_MBOX_OPCODE_READ_OBJECT                   0xAB
+#define LPFC_MBOX_OPCODE_WRITE_OBJECT                  0xAC
+#define LPFC_MBOX_OPCODE_READ_OBJECT_LIST              0xAD
+#define LPFC_MBOX_OPCODE_DELETE_OBJECT                 0xAE
+#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS           0xB5
 
 /* FCoE Opcodes */
 #define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE                        0x01
@@ -867,6 +880,7 @@ struct mbox_header {
 #define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF               0x0A
 #define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE                0x0B
 #define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF           0x10
+#define LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS      0x21
 #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE          0x22
 #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK       0x23
 
@@ -1337,11 +1351,11 @@ struct lpfc_mbx_set_link_diag_loopback {
                struct {
                        uint32_t word0;
 #define lpfc_mbx_set_diag_lpbk_type_SHIFT      0
-#define lpfc_mbx_set_diag_lpbk_type_MASK       0x00000001
+#define lpfc_mbx_set_diag_lpbk_type_MASK       0x00000003
 #define lpfc_mbx_set_diag_lpbk_type_WORD       word0
 #define LPFC_DIAG_LOOPBACK_TYPE_DISABLE                0x0
 #define LPFC_DIAG_LOOPBACK_TYPE_INTERNAL       0x1
-#define LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL       0x2
+#define LPFC_DIAG_LOOPBACK_TYPE_SERDES         0x2
 #define lpfc_mbx_set_diag_lpbk_link_num_SHIFT  16
 #define lpfc_mbx_set_diag_lpbk_link_num_MASK   0x0000003F
 #define lpfc_mbx_set_diag_lpbk_link_num_WORD   word0
@@ -1470,16 +1484,81 @@ struct sli4_sge {       /* SLI-4 */
        uint32_t addr_lo;
 
        uint32_t word2;
-#define lpfc_sli4_sge_offset_SHIFT     0 /* Offset of buffer - Not used*/
-#define lpfc_sli4_sge_offset_MASK      0x1FFFFFFF
+#define lpfc_sli4_sge_offset_SHIFT     0
+#define lpfc_sli4_sge_offset_MASK      0x07FFFFFF
 #define lpfc_sli4_sge_offset_WORD      word2
-#define lpfc_sli4_sge_last_SHIFT       31 /* Last SEG in the SGL sets
-                                               this  flag !! */
+#define lpfc_sli4_sge_type_SHIFT       27
+#define lpfc_sli4_sge_type_MASK                0x0000000F
+#define lpfc_sli4_sge_type_WORD                word2
+#define LPFC_SGE_TYPE_DATA             0x0
+#define LPFC_SGE_TYPE_DIF              0x4
+#define LPFC_SGE_TYPE_LSP              0x5
+#define LPFC_SGE_TYPE_PEDIF            0x6
+#define LPFC_SGE_TYPE_PESEED           0x7
+#define LPFC_SGE_TYPE_DISEED           0x8
+#define LPFC_SGE_TYPE_ENC              0x9
+#define LPFC_SGE_TYPE_ATM              0xA
+#define LPFC_SGE_TYPE_SKIP             0xC
+#define lpfc_sli4_sge_last_SHIFT       31 /* Last SEG in the SGL sets it */
 #define lpfc_sli4_sge_last_MASK                0x00000001
 #define lpfc_sli4_sge_last_WORD                word2
        uint32_t sge_len;
 };
 
+struct sli4_sge_diseed {       /* SLI-4 */
+       uint32_t ref_tag;
+       uint32_t ref_tag_tran;
+
+       uint32_t word2;
+#define lpfc_sli4_sge_dif_apptran_SHIFT        0
+#define lpfc_sli4_sge_dif_apptran_MASK 0x0000FFFF
+#define lpfc_sli4_sge_dif_apptran_WORD word2
+#define lpfc_sli4_sge_dif_af_SHIFT     24
+#define lpfc_sli4_sge_dif_af_MASK      0x00000001
+#define lpfc_sli4_sge_dif_af_WORD      word2
+#define lpfc_sli4_sge_dif_na_SHIFT     25
+#define lpfc_sli4_sge_dif_na_MASK      0x00000001
+#define lpfc_sli4_sge_dif_na_WORD      word2
+#define lpfc_sli4_sge_dif_hi_SHIFT     26
+#define lpfc_sli4_sge_dif_hi_MASK      0x00000001
+#define lpfc_sli4_sge_dif_hi_WORD      word2
+#define lpfc_sli4_sge_dif_type_SHIFT   27
+#define lpfc_sli4_sge_dif_type_MASK    0x0000000F
+#define lpfc_sli4_sge_dif_type_WORD    word2
+#define lpfc_sli4_sge_dif_last_SHIFT   31 /* Last SEG in the SGL sets it */
+#define lpfc_sli4_sge_dif_last_MASK    0x00000001
+#define lpfc_sli4_sge_dif_last_WORD    word2
+       uint32_t word3;
+#define lpfc_sli4_sge_dif_apptag_SHIFT 0
+#define lpfc_sli4_sge_dif_apptag_MASK  0x0000FFFF
+#define lpfc_sli4_sge_dif_apptag_WORD  word3
+#define lpfc_sli4_sge_dif_bs_SHIFT     16
+#define lpfc_sli4_sge_dif_bs_MASK      0x00000007
+#define lpfc_sli4_sge_dif_bs_WORD      word3
+#define lpfc_sli4_sge_dif_ai_SHIFT     19
+#define lpfc_sli4_sge_dif_ai_MASK      0x00000001
+#define lpfc_sli4_sge_dif_ai_WORD      word3
+#define lpfc_sli4_sge_dif_me_SHIFT     20
+#define lpfc_sli4_sge_dif_me_MASK      0x00000001
+#define lpfc_sli4_sge_dif_me_WORD      word3
+#define lpfc_sli4_sge_dif_re_SHIFT     21
+#define lpfc_sli4_sge_dif_re_MASK      0x00000001
+#define lpfc_sli4_sge_dif_re_WORD      word3
+#define lpfc_sli4_sge_dif_ce_SHIFT     22
+#define lpfc_sli4_sge_dif_ce_MASK      0x00000001
+#define lpfc_sli4_sge_dif_ce_WORD      word3
+#define lpfc_sli4_sge_dif_nr_SHIFT     23
+#define lpfc_sli4_sge_dif_nr_MASK      0x00000001
+#define lpfc_sli4_sge_dif_nr_WORD      word3
+#define lpfc_sli4_sge_dif_oprx_SHIFT   24
+#define lpfc_sli4_sge_dif_oprx_MASK    0x0000000F
+#define lpfc_sli4_sge_dif_oprx_WORD    word3
+#define lpfc_sli4_sge_dif_optx_SHIFT   28
+#define lpfc_sli4_sge_dif_optx_MASK    0x0000000F
+#define lpfc_sli4_sge_dif_optx_WORD    word3
+/* optx and oprx use BG_OP_IN defines in lpfc_hw.h */
+};
+
 struct fcf_record {
        uint32_t max_rcv_size;
        uint32_t fka_adv_period;
@@ -1751,6 +1830,8 @@ struct lpfc_mbx_init_vfi {
 #define lpfc_init_vfi_hop_count_MASK   0x000000FF
 #define lpfc_init_vfi_hop_count_WORD   word4
 };
+#define MBX_VFI_IN_USE                 0x9F02
+
 
 struct lpfc_mbx_reg_vfi {
        uint32_t word1;
@@ -2019,6 +2100,17 @@ struct lpfc_mbx_read_config {
 #define lpfc_mbx_rd_conf_extnts_inuse_MASK     0x00000001
 #define lpfc_mbx_rd_conf_extnts_inuse_WORD     word1
        uint32_t word2;
+#define lpfc_mbx_rd_conf_lnk_numb_SHIFT                0
+#define lpfc_mbx_rd_conf_lnk_numb_MASK         0x0000003F
+#define lpfc_mbx_rd_conf_lnk_numb_WORD         word2
+#define lpfc_mbx_rd_conf_lnk_type_SHIFT                6
+#define lpfc_mbx_rd_conf_lnk_type_MASK         0x00000003
+#define lpfc_mbx_rd_conf_lnk_type_WORD         word2
+#define LPFC_LNK_TYPE_GE       0
+#define LPFC_LNK_TYPE_FC       1
+#define lpfc_mbx_rd_conf_lnk_ldv_SHIFT         8
+#define lpfc_mbx_rd_conf_lnk_ldv_MASK          0x00000001
+#define lpfc_mbx_rd_conf_lnk_ldv_WORD          word2
 #define lpfc_mbx_rd_conf_topology_SHIFT                24
 #define lpfc_mbx_rd_conf_topology_MASK         0x000000FF
 #define lpfc_mbx_rd_conf_topology_WORD         word2
@@ -2552,8 +2644,152 @@ struct lpfc_mbx_get_prof_cfg {
        } u;
 };
 
+struct lpfc_controller_attribute {
+       uint32_t version_string[8];
+       uint32_t manufacturer_name[8];
+       uint32_t supported_modes;
+       uint32_t word17;
+#define lpfc_cntl_attr_eprom_ver_lo_SHIFT      0
+#define lpfc_cntl_attr_eprom_ver_lo_MASK       0x000000ff
+#define lpfc_cntl_attr_eprom_ver_lo_WORD       word17
+#define lpfc_cntl_attr_eprom_ver_hi_SHIFT      8
+#define lpfc_cntl_attr_eprom_ver_hi_MASK       0x000000ff
+#define lpfc_cntl_attr_eprom_ver_hi_WORD       word17
+       uint32_t mbx_da_struct_ver;
+       uint32_t ep_fw_da_struct_ver;
+       uint32_t ncsi_ver_str[3];
+       uint32_t dflt_ext_timeout;
+       uint32_t model_number[8];
+       uint32_t description[16];
+       uint32_t serial_number[8];
+       uint32_t ip_ver_str[8];
+       uint32_t fw_ver_str[8];
+       uint32_t bios_ver_str[8];
+       uint32_t redboot_ver_str[8];
+       uint32_t driver_ver_str[8];
+       uint32_t flash_fw_ver_str[8];
+       uint32_t functionality;
+       uint32_t word105;
+#define lpfc_cntl_attr_max_cbd_len_SHIFT       0
+#define lpfc_cntl_attr_max_cbd_len_MASK                0x0000ffff
+#define lpfc_cntl_attr_max_cbd_len_WORD                word105
+#define lpfc_cntl_attr_asic_rev_SHIFT          16
+#define lpfc_cntl_attr_asic_rev_MASK           0x000000ff
+#define lpfc_cntl_attr_asic_rev_WORD           word105
+#define lpfc_cntl_attr_gen_guid0_SHIFT         24
+#define lpfc_cntl_attr_gen_guid0_MASK          0x000000ff
+#define lpfc_cntl_attr_gen_guid0_WORD          word105
+       uint32_t gen_guid1_12[3];
+       uint32_t word109;
+#define lpfc_cntl_attr_gen_guid13_14_SHIFT     0
+#define lpfc_cntl_attr_gen_guid13_14_MASK      0x0000ffff
+#define lpfc_cntl_attr_gen_guid13_14_WORD      word109
+#define lpfc_cntl_attr_gen_guid15_SHIFT                16
+#define lpfc_cntl_attr_gen_guid15_MASK         0x000000ff
+#define lpfc_cntl_attr_gen_guid15_WORD         word109
+#define lpfc_cntl_attr_hba_port_cnt_SHIFT      24
+#define lpfc_cntl_attr_hba_port_cnt_MASK       0x000000ff
+#define lpfc_cntl_attr_hba_port_cnt_WORD       word109
+       uint32_t word110;
+#define lpfc_cntl_attr_dflt_lnk_tmo_SHIFT      0
+#define lpfc_cntl_attr_dflt_lnk_tmo_MASK       0x0000ffff
+#define lpfc_cntl_attr_dflt_lnk_tmo_WORD       word110
+#define lpfc_cntl_attr_multi_func_dev_SHIFT    24
+#define lpfc_cntl_attr_multi_func_dev_MASK     0x000000ff
+#define lpfc_cntl_attr_multi_func_dev_WORD     word110
+       uint32_t word111;
+#define lpfc_cntl_attr_cache_valid_SHIFT       0
+#define lpfc_cntl_attr_cache_valid_MASK                0x000000ff
+#define lpfc_cntl_attr_cache_valid_WORD                word111
+#define lpfc_cntl_attr_hba_status_SHIFT                8
+#define lpfc_cntl_attr_hba_status_MASK         0x000000ff
+#define lpfc_cntl_attr_hba_status_WORD         word111
+#define lpfc_cntl_attr_max_domain_SHIFT                16
+#define lpfc_cntl_attr_max_domain_MASK         0x000000ff
+#define lpfc_cntl_attr_max_domain_WORD         word111
+#define lpfc_cntl_attr_lnk_numb_SHIFT          24
+#define lpfc_cntl_attr_lnk_numb_MASK           0x0000003f
+#define lpfc_cntl_attr_lnk_numb_WORD           word111
+#define lpfc_cntl_attr_lnk_type_SHIFT          30
+#define lpfc_cntl_attr_lnk_type_MASK           0x00000003
+#define lpfc_cntl_attr_lnk_type_WORD           word111
+       uint32_t fw_post_status;
+       uint32_t hba_mtu[8];
+       uint32_t word121;
+       uint32_t reserved1[3];
+       uint32_t word125;
+#define lpfc_cntl_attr_pci_vendor_id_SHIFT     0
+#define lpfc_cntl_attr_pci_vendor_id_MASK      0x0000ffff
+#define lpfc_cntl_attr_pci_vendor_id_WORD      word125
+#define lpfc_cntl_attr_pci_device_id_SHIFT     16
+#define lpfc_cntl_attr_pci_device_id_MASK      0x0000ffff
+#define lpfc_cntl_attr_pci_device_id_WORD      word125
+       uint32_t word126;
+#define lpfc_cntl_attr_pci_subvdr_id_SHIFT     0
+#define lpfc_cntl_attr_pci_subvdr_id_MASK      0x0000ffff
+#define lpfc_cntl_attr_pci_subvdr_id_WORD      word126
+#define lpfc_cntl_attr_pci_subsys_id_SHIFT     16
+#define lpfc_cntl_attr_pci_subsys_id_MASK      0x0000ffff
+#define lpfc_cntl_attr_pci_subsys_id_WORD      word126
+       uint32_t word127;
+#define lpfc_cntl_attr_pci_bus_num_SHIFT       0
+#define lpfc_cntl_attr_pci_bus_num_MASK                0x000000ff
+#define lpfc_cntl_attr_pci_bus_num_WORD                word127
+#define lpfc_cntl_attr_pci_dev_num_SHIFT       8
+#define lpfc_cntl_attr_pci_dev_num_MASK                0x000000ff
+#define lpfc_cntl_attr_pci_dev_num_WORD                word127
+#define lpfc_cntl_attr_pci_fnc_num_SHIFT       16
+#define lpfc_cntl_attr_pci_fnc_num_MASK                0x000000ff
+#define lpfc_cntl_attr_pci_fnc_num_WORD                word127
+#define lpfc_cntl_attr_inf_type_SHIFT          24
+#define lpfc_cntl_attr_inf_type_MASK           0x000000ff
+#define lpfc_cntl_attr_inf_type_WORD           word127
+       uint32_t unique_id[2];
+       uint32_t word130;
+#define lpfc_cntl_attr_num_netfil_SHIFT                0
+#define lpfc_cntl_attr_num_netfil_MASK         0x000000ff
+#define lpfc_cntl_attr_num_netfil_WORD         word130
+       uint32_t reserved2[4];
+};
+
+struct lpfc_mbx_get_cntl_attributes {
+       union  lpfc_sli4_cfg_shdr cfg_shdr;
+       struct lpfc_controller_attribute cntl_attr;
+};
+
+struct lpfc_mbx_get_port_name {
+       struct mbox_header header;
+       union {
+               struct {
+                       uint32_t word4;
+#define lpfc_mbx_get_port_name_lnk_type_SHIFT  0
+#define lpfc_mbx_get_port_name_lnk_type_MASK   0x00000003
+#define lpfc_mbx_get_port_name_lnk_type_WORD   word4
+               } request;
+               struct {
+                       uint32_t word4;
+#define lpfc_mbx_get_port_name_name0_SHIFT     0
+#define lpfc_mbx_get_port_name_name0_MASK      0x000000FF
+#define lpfc_mbx_get_port_name_name0_WORD      word4
+#define lpfc_mbx_get_port_name_name1_SHIFT     8
+#define lpfc_mbx_get_port_name_name1_MASK      0x000000FF
+#define lpfc_mbx_get_port_name_name1_WORD      word4
+#define lpfc_mbx_get_port_name_name2_SHIFT     16
+#define lpfc_mbx_get_port_name_name2_MASK      0x000000FF
+#define lpfc_mbx_get_port_name_name2_WORD      word4
+#define lpfc_mbx_get_port_name_name3_SHIFT     24
+#define lpfc_mbx_get_port_name_name3_MASK      0x000000FF
+#define lpfc_mbx_get_port_name_name3_WORD      word4
+#define LPFC_LINK_NUMBER_0                     0
+#define LPFC_LINK_NUMBER_1                     1
+#define LPFC_LINK_NUMBER_2                     2
+#define LPFC_LINK_NUMBER_3                     3
+               } response;
+       } u;
+};
+
 /* Mailbox Completion Queue Error Messages */
-#define MB_CQE_STATUS_SUCCESS                  0x0
+#define MB_CQE_STATUS_SUCCESS                  0x0
 #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES  0x1
 #define MB_CQE_STATUS_INVALID_PARAMETER                0x2
 #define MB_CQE_STATUS_INSUFFICIENT_RESOURCES   0x3
@@ -2637,8 +2873,9 @@ struct lpfc_mqe {
                struct lpfc_mbx_run_link_diag_test link_diag_test;
                struct lpfc_mbx_get_func_cfg get_func_cfg;
                struct lpfc_mbx_get_prof_cfg get_prof_cfg;
-               struct lpfc_mbx_nop nop;
                struct lpfc_mbx_wr_object wr_object;
+               struct lpfc_mbx_get_port_name get_port_name;
+               struct lpfc_mbx_nop nop;
        } un;
 };
 
@@ -2855,6 +3092,9 @@ struct wqe_common {
 #define wqe_ctxt_tag_MASK     0x0000FFFF
 #define wqe_ctxt_tag_WORD     word6
        uint32_t word7;
+#define wqe_dif_SHIFT         0
+#define wqe_dif_MASK          0x00000003
+#define wqe_dif_WORD          word7
 #define wqe_ct_SHIFT          2
 #define wqe_ct_MASK           0x00000003
 #define wqe_ct_WORD           word7
@@ -2867,12 +3107,21 @@ struct wqe_common {
 #define wqe_class_SHIFT       16
 #define wqe_class_MASK        0x00000007
 #define wqe_class_WORD        word7
+#define wqe_ar_SHIFT          19
+#define wqe_ar_MASK           0x00000001
+#define wqe_ar_WORD           word7
+#define wqe_ag_SHIFT          wqe_ar_SHIFT
+#define wqe_ag_MASK           wqe_ar_MASK
+#define wqe_ag_WORD           wqe_ar_WORD
 #define wqe_pu_SHIFT          20
 #define wqe_pu_MASK           0x00000003
 #define wqe_pu_WORD           word7
 #define wqe_erp_SHIFT         22
 #define wqe_erp_MASK          0x00000001
 #define wqe_erp_WORD          word7
+#define wqe_conf_SHIFT        wqe_erp_SHIFT
+#define wqe_conf_MASK         wqe_erp_MASK
+#define wqe_conf_WORD         wqe_erp_WORD
 #define wqe_lnk_SHIFT         23
 #define wqe_lnk_MASK          0x00000001
 #define wqe_lnk_WORD          word7
@@ -2931,6 +3180,9 @@ struct wqe_common {
 #define wqe_xc_SHIFT          21
 #define wqe_xc_MASK           0x00000001
 #define wqe_xc_WORD           word10
+#define wqe_sr_SHIFT          22
+#define wqe_sr_MASK           0x00000001
+#define wqe_sr_WORD           word10
 #define wqe_ccpe_SHIFT        23
 #define wqe_ccpe_MASK         0x00000001
 #define wqe_ccpe_WORD         word10
@@ -3072,6 +3324,9 @@ struct wqe_rctl_dfctl {
 #define wqe_la_SHIFT 3
 #define wqe_la_MASK  0x000000001
 #define wqe_la_WORD  word5
+#define wqe_xo_SHIFT   6
+#define wqe_xo_MASK    0x000000001
+#define wqe_xo_WORD    word5
 #define wqe_ls_SHIFT 7
 #define wqe_ls_MASK  0x000000001
 #define wqe_ls_WORD  word5
index 027b797c991630d651e4955846a6af4dcc13cfc5..8ba4b5e0f933522383f90f9a2c93656c478a165a 100644 (file)
@@ -58,11 +58,9 @@ spinlock_t _dump_buf_lock;
 
 static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
 static int lpfc_post_rcv_buf(struct lpfc_hba *);
-static int lpfc_sli4_queue_create(struct lpfc_hba *);
-static void lpfc_sli4_queue_destroy(struct lpfc_hba *);
+static int lpfc_sli4_queue_verify(struct lpfc_hba *);
 static int lpfc_create_bootstrap_mbox(struct lpfc_hba *);
 static int lpfc_setup_endian_order(struct lpfc_hba *);
-static int lpfc_sli4_read_config(struct lpfc_hba *);
 static void lpfc_destroy_bootstrap_mbox(struct lpfc_hba *);
 static void lpfc_free_sgl_list(struct lpfc_hba *);
 static int lpfc_init_sgl_list(struct lpfc_hba *);
@@ -475,27 +473,6 @@ lpfc_config_port_post(struct lpfc_hba *phba)
        /* Get the default values for Model Name and Description */
        lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
 
-       if ((phba->cfg_link_speed > LPFC_USER_LINK_SPEED_16G)
-           || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_1G)
-               && !(phba->lmt & LMT_1Gb))
-           || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_2G)
-               && !(phba->lmt & LMT_2Gb))
-           || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_4G)
-               && !(phba->lmt & LMT_4Gb))
-           || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_8G)
-               && !(phba->lmt & LMT_8Gb))
-           || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G)
-               && !(phba->lmt & LMT_10Gb))
-           || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G)
-               && !(phba->lmt & LMT_16Gb))) {
-               /* Reset link speed to auto */
-               lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
-                       "1302 Invalid speed for this board: "
-                       "Reset link speed to auto: x%x\n",
-                       phba->cfg_link_speed);
-                       phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
-       }
-
        phba->link_state = LPFC_LINK_DOWN;
 
        /* Only process IOCBs on ELS ring till hba_state is READY */
@@ -585,28 +562,10 @@ lpfc_config_port_post(struct lpfc_hba *phba)
                        return -EIO;
                }
        } else if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) {
-               lpfc_init_link(phba, pmb, phba->cfg_topology,
-                       phba->cfg_link_speed);
-               pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               lpfc_set_loopback_flag(phba);
-               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-               if (rc != MBX_SUCCESS) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "0454 Adapter failed to init, mbxCmd x%x "
-                               "INIT_LINK, mbxStatus x%x\n",
-                               mb->mbxCommand, mb->mbxStatus);
-
-                       /* Clear all interrupt enable conditions */
-                       writel(0, phba->HCregaddr);
-                       readl(phba->HCregaddr); /* flush */
-                       /* Clear all pending interrupts */
-                       writel(0xffffffff, phba->HAregaddr);
-                       readl(phba->HAregaddr); /* flush */
-                       phba->link_state = LPFC_HBA_ERROR;
-                       if (rc != MBX_BUSY)
-                               mempool_free(pmb, phba->mbox_mem_pool);
-                       return -EIO;
-               }
+               mempool_free(pmb, phba->mbox_mem_pool);
+               rc = phba->lpfc_hba_init_link(phba);
+               if (rc)
+                       return rc;
        }
        /* MBOX buffer will be freed in mbox compl */
        pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -654,7 +613,6 @@ lpfc_config_port_post(struct lpfc_hba *phba)
 /**
  * lpfc_hba_init_link - Initialize the FC link
  * @phba: pointer to lpfc hba data structure.
- * @flag: mailbox command issue mode - either MBX_POLL or MBX_NOWAIT
  *
  * This routine will issue the INIT_LINK mailbox command call.
  * It is available to other drivers through the lpfc_hba data
@@ -666,7 +624,27 @@ lpfc_config_port_post(struct lpfc_hba *phba)
  *             Any other value - error
  **/
 int
-lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag)
+lpfc_hba_init_link(struct lpfc_hba *phba)
+{
+       return lpfc_hba_init_link_fc_topology(phba, phba->cfg_topology);
+}
+
+/**
+ * lpfc_hba_init_link_fc_topology - Initialize FC link with desired topology
+ * @phba: pointer to lpfc hba data structure.
+ * @fc_topology: desired fc topology.
+ *
+ * This routine will issue the INIT_LINK mailbox command call.
+ * It is available to other drivers through the lpfc_hba data
+ * structure for use as a delayed link up mechanism with the
+ * module parameter lpfc_suppress_link_up.
+ *
+ * Return code
+ *              0 - success
+ *              Any other value - error
+ **/
+int
+lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology)
 {
        struct lpfc_vport *vport = phba->pport;
        LPFC_MBOXQ_t *pmb;
@@ -681,10 +659,31 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag)
        mb = &pmb->u.mb;
        pmb->vport = vport;
 
-       lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
+       if ((phba->cfg_link_speed > LPFC_USER_LINK_SPEED_MAX) ||
+           ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_1G) &&
+            !(phba->lmt & LMT_1Gb)) ||
+           ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_2G) &&
+            !(phba->lmt & LMT_2Gb)) ||
+           ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_4G) &&
+            !(phba->lmt & LMT_4Gb)) ||
+           ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_8G) &&
+            !(phba->lmt & LMT_8Gb)) ||
+           ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G) &&
+            !(phba->lmt & LMT_10Gb)) ||
+           ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) &&
+            !(phba->lmt & LMT_16Gb))) {
+               /* Reset link speed to auto */
+               lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+                       "1302 Invalid speed for this board:%d "
+                       "Reset link speed to auto.\n",
+                       phba->cfg_link_speed);
+                       phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
+       }
+       lpfc_init_link(phba, pmb, fc_topology, phba->cfg_link_speed);
        pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-       lpfc_set_loopback_flag(phba);
-       rc = lpfc_sli_issue_mbox(phba, pmb, flag);
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               lpfc_set_loopback_flag(phba);
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
        if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                        "0498 Adapter failed to init, mbxCmd x%x "
@@ -699,13 +698,11 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag)
                        readl(phba->HAregaddr); /* flush */
                }
                phba->link_state = LPFC_HBA_ERROR;
-               if (rc != MBX_BUSY || flag == MBX_POLL)
+               if (rc != MBX_BUSY)
                        mempool_free(pmb, phba->mbox_mem_pool);
                return -EIO;
        }
        phba->cfg_suppress_link_up = LPFC_INITIALIZE_LINK;
-       if (flag == MBX_POLL)
-               mempool_free(pmb, phba->mbox_mem_pool);
 
        return 0;
 }
@@ -713,7 +710,6 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag)
 /**
  * lpfc_hba_down_link - this routine downs the FC link
  * @phba: pointer to lpfc hba data structure.
- * @flag: mailbox command issue mode - either MBX_POLL or MBX_NOWAIT
  *
  * This routine will issue the DOWN_LINK mailbox command call.
  * It is available to other drivers through the lpfc_hba data
@@ -724,7 +720,7 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag)
  *             Any other value - error
  **/
 int
-lpfc_hba_down_link(struct lpfc_hba *phba, uint32_t flag)
+lpfc_hba_down_link(struct lpfc_hba *phba)
 {
        LPFC_MBOXQ_t *pmb;
        int rc;
@@ -740,7 +736,7 @@ lpfc_hba_down_link(struct lpfc_hba *phba, uint32_t flag)
                "0491 Adapter Link is disabled.\n");
        lpfc_down_link(phba, pmb);
        pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-       rc = lpfc_sli_issue_mbox(phba, pmb, flag);
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
        if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) {
                lpfc_printf_log(phba,
                KERN_ERR, LOG_INIT,
@@ -750,9 +746,6 @@ lpfc_hba_down_link(struct lpfc_hba *phba, uint32_t flag)
                mempool_free(pmb, phba->mbox_mem_pool);
                return -EIO;
        }
-       if (flag == MBX_POLL)
-               mempool_free(pmb, phba->mbox_mem_pool);
-
        return 0;
 }
 
@@ -1393,8 +1386,7 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba)
                fc_host_post_vendor_event(shost, fc_get_event_number(),
                                          sizeof(temp_event_data),
                                          (char *) &temp_event_data,
-                                         SCSI_NL_VID_TYPE_PCI
-                                         | PCI_VENDOR_ID_EMULEX);
+                                         LPFC_NL_VENDOR_ID);
 
                spin_lock_irq(&phba->hbalock);
                phba->over_temp_state = HBA_OVER_TEMP;
@@ -1416,7 +1408,7 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba)
                shost = lpfc_shost_from_vport(vport);
                fc_host_post_vendor_event(shost, fc_get_event_number(),
                                sizeof(event_data), (char *) &event_data,
-                               SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+                               LPFC_NL_VENDOR_ID);
 
                lpfc_offline_eratt(phba);
        }
@@ -1437,7 +1429,11 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
        uint32_t event_data;
        struct Scsi_Host *shost;
        uint32_t if_type;
-       struct lpfc_register portstat_reg;
+       struct lpfc_register portstat_reg = {0};
+       uint32_t reg_err1, reg_err2;
+       uint32_t uerrlo_reg, uemasklo_reg;
+       uint32_t pci_rd_rc1, pci_rd_rc2;
+       int rc;
 
        /* If the pci channel is offline, ignore possible errors, since
         * we cannot communicate with the pci card anyway.
@@ -1448,48 +1444,75 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
        if (!phba->cfg_enable_hba_reset)
                return;
 
-       /* Send an internal error event to mgmt application */
-       lpfc_board_errevt_to_mgmt(phba);
-
-       /* For now, the actual action for SLI4 device handling is not
-        * specified yet, just treated it as adaptor hardware failure
-        */
-       event_data = FC_REG_DUMP_EVENT;
-       shost = lpfc_shost_from_vport(vport);
-       fc_host_post_vendor_event(shost, fc_get_event_number(),
-                                 sizeof(event_data), (char *) &event_data,
-                                 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-
        if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
        switch (if_type) {
        case LPFC_SLI_INTF_IF_TYPE_0:
+               pci_rd_rc1 = lpfc_readl(
+                               phba->sli4_hba.u.if_type0.UERRLOregaddr,
+                               &uerrlo_reg);
+               pci_rd_rc2 = lpfc_readl(
+                               phba->sli4_hba.u.if_type0.UEMASKLOregaddr,
+                               &uemasklo_reg);
+               /* consider PCI bus read error as pci_channel_offline */
+               if (pci_rd_rc1 == -EIO && pci_rd_rc2 == -EIO)
+                       return;
                lpfc_sli4_offline_eratt(phba);
                break;
        case LPFC_SLI_INTF_IF_TYPE_2:
-               portstat_reg.word0 =
-                       readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
-
+               pci_rd_rc1 = lpfc_readl(
+                               phba->sli4_hba.u.if_type2.STATUSregaddr,
+                               &portstat_reg.word0);
+               /* consider PCI bus read error as pci_channel_offline */
+               if (pci_rd_rc1 == -EIO)
+                       return;
+               reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
+               reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
                if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) {
                        /* TODO: Register for Overtemp async events. */
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "2889 Port Overtemperature event, "
-                               "taking port\n");
+                               "taking port offline\n");
                        spin_lock_irq(&phba->hbalock);
                        phba->over_temp_state = HBA_OVER_TEMP;
                        spin_unlock_irq(&phba->hbalock);
                        lpfc_sli4_offline_eratt(phba);
-                       return;
+                       break;
                }
-               if (bf_get(lpfc_sliport_status_rn, &portstat_reg)) {
-                       /*
-                        * TODO: Attempt port recovery via a port reset.
-                        * When fully implemented, the driver should
-                        * attempt to recover the port here and return.
-                        * For now, log an error and take the port offline.
-                        */
+               if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 &&
+                   reg_err2 == SLIPORT_ERR2_REG_FW_RESTART)
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "3143 Port Down: Firmware Restarted\n");
+               else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 &&
+                        reg_err2 == SLIPORT_ERR2_REG_FORCED_DUMP)
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "3144 Port Down: Debug Dump\n");
+               else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 &&
+                        reg_err2 == SLIPORT_ERR2_REG_FUNC_PROVISON)
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "2887 Port Error: Attempting "
-                                       "Port Recovery\n");
+                                       "3145 Port Down: Provisioning\n");
+               /*
+                * On error status condition, driver need to wait for port
+                * ready before performing reset.
+                */
+               rc = lpfc_sli4_pdev_status_reg_wait(phba);
+               if (!rc) {
+                       /* need reset: attempt for port recovery */
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "2887 Reset Needed: Attempting Port "
+                                       "Recovery...\n");
+                       lpfc_offline_prep(phba);
+                       lpfc_offline(phba);
+                       lpfc_sli_brdrestart(phba);
+                       if (lpfc_online(phba) == 0) {
+                               lpfc_unblock_mgmt_io(phba);
+                               /* don't report event on forced debug dump */
+                               if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 &&
+                                   reg_err2 == SLIPORT_ERR2_REG_FORCED_DUMP)
+                                       return;
+                               else
+                                       break;
+                       }
+                       /* fall through for not able to recover */
                }
                lpfc_sli4_offline_eratt(phba);
                break;
@@ -1497,6 +1520,16 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
        default:
                break;
        }
+       lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+                       "3123 Report dump event to upper layer\n");
+       /* Send an internal error event to mgmt application */
+       lpfc_board_errevt_to_mgmt(phba);
+
+       event_data = FC_REG_DUMP_EVENT;
+       shost = lpfc_shost_from_vport(vport);
+       fc_host_post_vendor_event(shost, fc_get_event_number(),
+                                 sizeof(event_data), (char *) &event_data,
+                                 SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
 }
 
 /**
@@ -1724,11 +1757,20 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
                                j = 0;
                                Length -= (3+i);
                                while(i--) {
-                               phba->Port[j++] = vpd[index++];
-                               if (j == 19)
-                                       break;
+                                       if ((phba->sli_rev == LPFC_SLI_REV4) &&
+                                           (phba->sli4_hba.pport_name_sta ==
+                                            LPFC_SLI4_PPNAME_GET)) {
+                                               j++;
+                                               index++;
+                                       } else
+                                               phba->Port[j++] = vpd[index++];
+                                       if (j == 19)
+                                               break;
                                }
-                               phba->Port[j] = 0;
+                               if ((phba->sli_rev != LPFC_SLI_REV4) ||
+                                   (phba->sli4_hba.pport_name_sta ==
+                                    LPFC_SLI4_PPNAME_NON))
+                                       phba->Port[j] = 0;
                                continue;
                        }
                        else {
@@ -1958,7 +2000,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
        case PCI_DEVICE_ID_LANCER_FCOE:
        case PCI_DEVICE_ID_LANCER_FCOE_VF:
                oneConnect = 1;
-               m = (typeof(m)){"OCe50100", "PCIe", "FCoE"};
+               m = (typeof(m)){"OCe15100", "PCIe", "FCoE"};
                break;
        default:
                m = (typeof(m)){"Unknown", "", ""};
@@ -2432,17 +2474,19 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
        uint8_t actcmd = MBX_HEARTBEAT;
        unsigned long timeout;
 
-
+       timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies;
        spin_lock_irqsave(&phba->hbalock, iflag);
        phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
-       if (phba->sli.mbox_active)
+       if (phba->sli.mbox_active) {
                actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
+               /* Determine how long we might wait for the active mailbox
+                * command to be gracefully completed by firmware.
+                */
+               timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+                               phba->sli.mbox_active) * 1000) + jiffies;
+       }
        spin_unlock_irqrestore(&phba->hbalock, iflag);
-       /* Determine how long we might wait for the active mailbox
-        * command to be gracefully completed by firmware.
-        */
-       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
-                       jiffies;
+
        /* Wait for the outstnading mailbox command to complete */
        while (phba->sli.mbox_active) {
                /* Check active mailbox complete status every 2ms */
@@ -2653,6 +2697,32 @@ lpfc_offline(struct lpfc_hba *phba)
        lpfc_destroy_vport_work_array(phba, vports);
 }
 
+/**
+ * lpfc_scsi_buf_update - Update the scsi_buffers that are already allocated.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine goes through all the scsi buffers in the system and updates the
+ * Physical XRIs assigned to the SCSI buffer because these may change after any
+ * firmware reset
+ *
+ * Return codes
+ *   0 - successful (for now, it always returns 0)
+ **/
+int
+lpfc_scsi_buf_update(struct lpfc_hba *phba)
+{
+       struct lpfc_scsi_buf *sb, *sb_next;
+
+       spin_lock_irq(&phba->hbalock);
+       spin_lock(&phba->scsi_buf_list_lock);
+       list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list)
+               sb->cur_iocbq.sli4_xritag =
+                       phba->sli4_hba.xri_ids[sb->cur_iocbq.sli4_lxritag];
+       spin_unlock(&phba->scsi_buf_list_lock);
+       spin_unlock_irq(&phba->hbalock);
+       return 0;
+}
+
 /**
  * lpfc_scsi_free - Free all the SCSI buffers and IOCBs from driver lists
  * @phba: pointer to lpfc hba data structure.
@@ -2944,8 +3014,6 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
                (((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
                (uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
 
-       fc_host_dev_loss_tmo(shost) = vport->cfg_devloss_tmo;
-
        /* This value is also unchanging */
        memset(fc_host_active_fc4s(shost), 0,
               sizeof(fc_host_active_fc4s(shost)));
@@ -3634,8 +3702,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
                        lpfc_sli4_fcf_dead_failthrough(phba);
                } else {
                        /* Reset FCF roundrobin bmask for new discovery */
-                       memset(phba->fcf.fcf_rr_bmask, 0,
-                              sizeof(*phba->fcf.fcf_rr_bmask));
+                       lpfc_sli4_clear_fcf_rr_bmask(phba);
                        /*
                         * Handling fast FCF failover to a DEAD FCF event is
                         * considered equalivant to receiving CVL to all vports.
@@ -3721,8 +3788,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
                                 * Reset FCF roundrobin bmask for new
                                 * discovery.
                                 */
-                               memset(phba->fcf.fcf_rr_bmask, 0,
-                                      sizeof(*phba->fcf.fcf_rr_bmask));
+                               lpfc_sli4_clear_fcf_rr_bmask(phba);
                }
                break;
        default:
@@ -3951,7 +4017,7 @@ static int
 lpfc_enable_pci_dev(struct lpfc_hba *phba)
 {
        struct pci_dev *pdev;
-       int bars;
+       int bars = 0;
 
        /* Obtain PCI device reference */
        if (!phba->pcidev)
@@ -3980,6 +4046,8 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba)
 out_disable_device:
        pci_disable_device(pdev);
 out_error:
+       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "1401 Failed to enable pci device, bars:x%x\n", bars);
        return -ENODEV;
 }
 
@@ -4053,9 +4121,6 @@ lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba)
        uint16_t nr_virtfn;
        int pos;
 
-       if (!pdev->is_physfn)
-               return 0;
-
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
        if (pos == 0)
                return 0;
@@ -4476,15 +4541,15 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                }
        }
        mempool_free(mboxq, phba->mbox_mem_pool);
-       /* Create all the SLI4 queues */
-       rc = lpfc_sli4_queue_create(phba);
+       /* Verify all the SLI4 queues */
+       rc = lpfc_sli4_queue_verify(phba);
        if (rc)
                goto out_free_bsmbx;
 
        /* Create driver internal CQE event pool */
        rc = lpfc_sli4_cq_event_pool_create(phba);
        if (rc)
-               goto out_destroy_queue;
+               goto out_free_bsmbx;
 
        /* Initialize and populate the iocb list per host */
        rc = lpfc_init_sgl_list(phba);
@@ -4518,14 +4583,21 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                goto out_remove_rpi_hdrs;
        }
 
-       phba->sli4_hba.fcp_eq_hdl = kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
+       /* 
+        * The cfg_fcp_eq_count can be zero whenever there is exactly one
+        * interrupt vector.  This is not an error
+        */
+       if (phba->cfg_fcp_eq_count) {
+               phba->sli4_hba.fcp_eq_hdl =
+                               kzalloc((sizeof(struct lpfc_fcp_eq_hdl) *
                                    phba->cfg_fcp_eq_count), GFP_KERNEL);
-       if (!phba->sli4_hba.fcp_eq_hdl) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "2572 Failed allocate memory for fast-path "
-                               "per-EQ handle array\n");
-               rc = -ENOMEM;
-               goto out_free_fcf_rr_bmask;
+               if (!phba->sli4_hba.fcp_eq_hdl) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "2572 Failed allocate memory for "
+                                       "fast-path per-EQ handle array\n");
+                       rc = -ENOMEM;
+                       goto out_free_fcf_rr_bmask;
+               }
        }
 
        phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) *
@@ -4569,8 +4641,6 @@ out_free_sgl_list:
        lpfc_free_sgl_list(phba);
 out_destroy_cq_event_pool:
        lpfc_sli4_cq_event_pool_destroy(phba);
-out_destroy_queue:
-       lpfc_sli4_queue_destroy(phba);
 out_free_bsmbx:
        lpfc_destroy_bootstrap_mbox(phba);
 out_free_mem:
@@ -4610,9 +4680,6 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
        /* Free the SCSI sgl management array */
        kfree(phba->sli4_hba.lpfc_scsi_psb_array);
 
-       /* Free the SLI4 queues */
-       lpfc_sli4_queue_destroy(phba);
-
        /* Free the completion queue EQ event pool */
        lpfc_sli4_cq_event_release_all(phba);
        lpfc_sli4_cq_event_pool_destroy(phba);
@@ -5021,15 +5088,8 @@ lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba)
        struct lpfc_rpi_hdr *rpi_hdr;
 
        INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_hdr_list);
-       /*
-        * If the SLI4 port supports extents, posting the rpi header isn't
-        * required.  Set the expected maximum count and let the actual value
-        * get set when extents are fully allocated.
-        */
-       if (!phba->sli4_hba.rpi_hdrs_in_use) {
-               phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.max_rpi;
+       if (!phba->sli4_hba.rpi_hdrs_in_use)
                return rc;
-       }
        if (phba->sli4_hba.extents_in_use)
                return -EIO;
 
@@ -5923,7 +5983,7 @@ lpfc_destroy_bootstrap_mbox(struct lpfc_hba *phba)
  *     -ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
-static int
+int
 lpfc_sli4_read_config(struct lpfc_hba *phba)
 {
        LPFC_MBOXQ_t *pmb;
@@ -5955,6 +6015,20 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
                rc = -EIO;
        } else {
                rd_config = &pmb->u.mqe.un.rd_config;
+               if (bf_get(lpfc_mbx_rd_conf_lnk_ldv, rd_config)) {
+                       phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL;
+                       phba->sli4_hba.lnk_info.lnk_tp =
+                               bf_get(lpfc_mbx_rd_conf_lnk_type, rd_config);
+                       phba->sli4_hba.lnk_info.lnk_no =
+                               bf_get(lpfc_mbx_rd_conf_lnk_numb, rd_config);
+                       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                                       "3081 lnk_type:%d, lnk_numb:%d\n",
+                                       phba->sli4_hba.lnk_info.lnk_tp,
+                                       phba->sli4_hba.lnk_info.lnk_no);
+               } else
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                                       "3082 Mailbox (x%x) returned ldv:x0\n",
+                                       bf_get(lpfc_mqe_command, &pmb->u.mqe));
                phba->sli4_hba.extents_in_use =
                        bf_get(lpfc_mbx_rd_conf_extnts_inuse, rd_config);
                phba->sli4_hba.max_cfg_param.max_xri =
@@ -6141,24 +6215,21 @@ lpfc_setup_endian_order(struct lpfc_hba *phba)
 }
 
 /**
- * lpfc_sli4_queue_create - Create all the SLI4 queues
+ * lpfc_sli4_queue_verify - Verify and update EQ and CQ counts
  * @phba: pointer to lpfc hba data structure.
  *
- * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA
- * operation. For each SLI4 queue type, the parameters such as queue entry
- * count (queue depth) shall be taken from the module parameter. For now,
- * we just use some constant number as place holder.
+ * This routine is invoked to check the user settable queue counts for EQs and
+ * CQs. after this routine is called the counts will be set to valid values that
+ * adhere to the constraints of the system's interrupt vectors and the port's
+ * queue resources.
  *
  * Return codes
  *      0 - successful
  *      -ENOMEM - No available memory
- *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
-lpfc_sli4_queue_create(struct lpfc_hba *phba)
+lpfc_sli4_queue_verify(struct lpfc_hba *phba)
 {
-       struct lpfc_queue *qdesc;
-       int fcp_eqidx, fcp_cqidx, fcp_wqidx;
        int cfg_fcp_wq_count;
        int cfg_fcp_eq_count;
 
@@ -6231,14 +6302,43 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
        /* The overall number of event queues used */
        phba->sli4_hba.cfg_eqn = phba->cfg_fcp_eq_count + LPFC_SP_EQN_DEF;
 
-       /*
-        * Create Event Queues (EQs)
-        */
-
        /* Get EQ depth from module parameter, fake the default for now */
        phba->sli4_hba.eq_esize = LPFC_EQE_SIZE_4B;
        phba->sli4_hba.eq_ecount = LPFC_EQE_DEF_COUNT;
 
+       /* Get CQ depth from module parameter, fake the default for now */
+       phba->sli4_hba.cq_esize = LPFC_CQE_SIZE;
+       phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT;
+
+       return 0;
+out_error:
+       return -ENOMEM;
+}
+
+/**
+ * lpfc_sli4_queue_create - Create all the SLI4 queues
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to allocate all the SLI4 queues for the FCoE HBA
+ * operation. For each SLI4 queue type, the parameters such as queue entry
+ * count (queue depth) shall be taken from the module parameter. For now,
+ * we just use some constant number as place holder.
+ *
+ * Return codes
+ *      0 - sucessful
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
+ **/
+int
+lpfc_sli4_queue_create(struct lpfc_hba *phba)
+{
+       struct lpfc_queue *qdesc;
+       int fcp_eqidx, fcp_cqidx, fcp_wqidx;
+
+       /*
+        * Create Event Queues (EQs)
+        */
+
        /* Create slow path event queue */
        qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize,
                                      phba->sli4_hba.eq_ecount);
@@ -6249,14 +6349,20 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
        }
        phba->sli4_hba.sp_eq = qdesc;
 
-       /* Create fast-path FCP Event Queue(s) */
-       phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) *
-                              phba->cfg_fcp_eq_count), GFP_KERNEL);
-       if (!phba->sli4_hba.fp_eq) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "2576 Failed allocate memory for fast-path "
-                               "EQ record array\n");
-               goto out_free_sp_eq;
+       /*
+        * Create fast-path FCP Event Queue(s).  The cfg_fcp_eq_count can be
+        * zero whenever there is exactly one interrupt vector.  This is not
+        * an error.
+        */
+       if (phba->cfg_fcp_eq_count) {
+               phba->sli4_hba.fp_eq = kzalloc((sizeof(struct lpfc_queue *) *
+                                      phba->cfg_fcp_eq_count), GFP_KERNEL);
+               if (!phba->sli4_hba.fp_eq) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "2576 Failed allocate memory for "
+                                       "fast-path EQ record array\n");
+                       goto out_free_sp_eq;
+               }
        }
        for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) {
                qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.eq_esize,
@@ -6273,10 +6379,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
         * Create Complete Queues (CQs)
         */
 
-       /* Get CQ depth from module parameter, fake the default for now */
-       phba->sli4_hba.cq_esize = LPFC_CQE_SIZE;
-       phba->sli4_hba.cq_ecount = LPFC_CQE_DEF_COUNT;
-
        /* Create slow-path Mailbox Command Complete Queue */
        qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
                                      phba->sli4_hba.cq_ecount);
@@ -6298,16 +6400,25 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
        phba->sli4_hba.els_cq = qdesc;
 
 
-       /* Create fast-path FCP Completion Queue(s), one-to-one with EQs */
-       phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) *
-                               phba->cfg_fcp_eq_count), GFP_KERNEL);
+       /*
+        * Create fast-path FCP Completion Queue(s), one-to-one with FCP EQs.
+        * If there are no FCP EQs then create exactly one FCP CQ.
+        */
+       if (phba->cfg_fcp_eq_count)
+               phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) *
+                                                phba->cfg_fcp_eq_count),
+                                               GFP_KERNEL);
+       else
+               phba->sli4_hba.fcp_cq = kzalloc(sizeof(struct lpfc_queue *),
+                                               GFP_KERNEL);
        if (!phba->sli4_hba.fcp_cq) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "2577 Failed allocate memory for fast-path "
                                "CQ record array\n");
                goto out_free_els_cq;
        }
-       for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) {
+       fcp_cqidx = 0;
+       do {
                qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
                                              phba->sli4_hba.cq_ecount);
                if (!qdesc) {
@@ -6317,7 +6428,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
                        goto out_free_fcp_cq;
                }
                phba->sli4_hba.fcp_cq[fcp_cqidx] = qdesc;
-       }
+       } while (++fcp_cqidx < phba->cfg_fcp_eq_count);
 
        /* Create Mailbox Command Queue */
        phba->sli4_hba.mq_esize = LPFC_MQE_SIZE;
@@ -6406,6 +6517,7 @@ out_free_fcp_wq:
                phba->sli4_hba.fcp_wq[fcp_wqidx] = NULL;
        }
        kfree(phba->sli4_hba.fcp_wq);
+       phba->sli4_hba.fcp_wq = NULL;
 out_free_els_wq:
        lpfc_sli4_queue_free(phba->sli4_hba.els_wq);
        phba->sli4_hba.els_wq = NULL;
@@ -6418,6 +6530,7 @@ out_free_fcp_cq:
                phba->sli4_hba.fcp_cq[fcp_cqidx] = NULL;
        }
        kfree(phba->sli4_hba.fcp_cq);
+       phba->sli4_hba.fcp_cq = NULL;
 out_free_els_cq:
        lpfc_sli4_queue_free(phba->sli4_hba.els_cq);
        phba->sli4_hba.els_cq = NULL;
@@ -6430,6 +6543,7 @@ out_free_fp_eq:
                phba->sli4_hba.fp_eq[fcp_eqidx] = NULL;
        }
        kfree(phba->sli4_hba.fp_eq);
+       phba->sli4_hba.fp_eq = NULL;
 out_free_sp_eq:
        lpfc_sli4_queue_free(phba->sli4_hba.sp_eq);
        phba->sli4_hba.sp_eq = NULL;
@@ -6449,7 +6563,7 @@ out_error:
  *      -ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
-static void
+void
 lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
 {
        int fcp_qidx;
@@ -6463,8 +6577,10 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
        phba->sli4_hba.els_wq = NULL;
 
        /* Release FCP work queue */
-       for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++)
-               lpfc_sli4_queue_free(phba->sli4_hba.fcp_wq[fcp_qidx]);
+       if (phba->sli4_hba.fcp_wq != NULL)
+               for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count;
+                    fcp_qidx++)
+                       lpfc_sli4_queue_free(phba->sli4_hba.fcp_wq[fcp_qidx]);
        kfree(phba->sli4_hba.fcp_wq);
        phba->sli4_hba.fcp_wq = NULL;
 
@@ -6484,15 +6600,18 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
 
        /* Release FCP response complete queue */
        fcp_qidx = 0;
-       do
-               lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]);
-       while (++fcp_qidx < phba->cfg_fcp_eq_count);
+       if (phba->sli4_hba.fcp_cq != NULL)
+               do
+                       lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]);
+               while (++fcp_qidx < phba->cfg_fcp_eq_count);
        kfree(phba->sli4_hba.fcp_cq);
        phba->sli4_hba.fcp_cq = NULL;
 
        /* Release fast-path event queue */
-       for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
-               lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]);
+       if (phba->sli4_hba.fp_eq != NULL)
+               for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count;
+                    fcp_qidx++)
+                       lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]);
        kfree(phba->sli4_hba.fp_eq);
        phba->sli4_hba.fp_eq = NULL;
 
@@ -6545,11 +6664,18 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                        phba->sli4_hba.sp_eq->queue_id);
 
        /* Set up fast-path event queue */
+       if (phba->cfg_fcp_eq_count && !phba->sli4_hba.fp_eq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3147 Fast-path EQs not allocated\n");
+               rc = -ENOMEM;
+               goto out_destroy_sp_eq;
+       }
        for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) {
                if (!phba->sli4_hba.fp_eq[fcp_eqidx]) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                        "0522 Fast-path EQ (%d) not "
                                        "allocated\n", fcp_eqidx);
+                       rc = -ENOMEM;
                        goto out_destroy_fp_eq;
                }
                rc = lpfc_eq_create(phba, phba->sli4_hba.fp_eq[fcp_eqidx],
@@ -6574,6 +6700,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
        if (!phba->sli4_hba.mbx_cq) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0528 Mailbox CQ not allocated\n");
+               rc = -ENOMEM;
                goto out_destroy_fp_eq;
        }
        rc = lpfc_cq_create(phba, phba->sli4_hba.mbx_cq, phba->sli4_hba.sp_eq,
@@ -6593,6 +6720,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
        if (!phba->sli4_hba.els_cq) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0530 ELS CQ not allocated\n");
+               rc = -ENOMEM;
                goto out_destroy_mbx_cq;
        }
        rc = lpfc_cq_create(phba, phba->sli4_hba.els_cq, phba->sli4_hba.sp_eq,
@@ -6609,12 +6737,20 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                        phba->sli4_hba.sp_eq->queue_id);
 
        /* Set up fast-path FCP Response Complete Queue */
+       if (!phba->sli4_hba.fcp_cq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3148 Fast-path FCP CQ array not "
+                               "allocated\n");
+               rc = -ENOMEM;
+               goto out_destroy_els_cq;
+       }
        fcp_cqidx = 0;
        do {
                if (!phba->sli4_hba.fcp_cq[fcp_cqidx]) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                        "0526 Fast-path FCP CQ (%d) not "
                                        "allocated\n", fcp_cqidx);
+                       rc = -ENOMEM;
                        goto out_destroy_fcp_cq;
                }
                if (phba->cfg_fcp_eq_count)
@@ -6653,6 +6789,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
        if (!phba->sli4_hba.mbx_wq) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0538 Slow-path MQ not allocated\n");
+               rc = -ENOMEM;
                goto out_destroy_fcp_cq;
        }
        rc = lpfc_mq_create(phba, phba->sli4_hba.mbx_wq,
@@ -6672,6 +6809,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
        if (!phba->sli4_hba.els_wq) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0536 Slow-path ELS WQ not allocated\n");
+               rc = -ENOMEM;
                goto out_destroy_mbx_wq;
        }
        rc = lpfc_wq_create(phba, phba->sli4_hba.els_wq,
@@ -6688,11 +6826,19 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                        phba->sli4_hba.els_cq->queue_id);
 
        /* Set up fast-path FCP Work Queue */
+       if (!phba->sli4_hba.fcp_wq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3149 Fast-path FCP WQ array not "
+                               "allocated\n");
+               rc = -ENOMEM;
+               goto out_destroy_els_wq;
+       }
        for (fcp_wqidx = 0; fcp_wqidx < phba->cfg_fcp_wq_count; fcp_wqidx++) {
                if (!phba->sli4_hba.fcp_wq[fcp_wqidx]) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                        "0534 Fast-path FCP WQ (%d) not "
                                        "allocated\n", fcp_wqidx);
+                       rc = -ENOMEM;
                        goto out_destroy_fcp_wq;
                }
                rc = lpfc_wq_create(phba, phba->sli4_hba.fcp_wq[fcp_wqidx],
@@ -6723,8 +6869,13 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
        if (!phba->sli4_hba.hdr_rq || !phba->sli4_hba.dat_rq) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0540 Receive Queue not allocated\n");
+               rc = -ENOMEM;
                goto out_destroy_fcp_wq;
        }
+
+       lpfc_rq_adjust_repost(phba, phba->sli4_hba.hdr_rq, LPFC_ELS_HBQ);
+       lpfc_rq_adjust_repost(phba, phba->sli4_hba.dat_rq, LPFC_ELS_HBQ);
+
        rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq,
                            phba->sli4_hba.els_cq, LPFC_USOL);
        if (rc) {
@@ -6733,6 +6884,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                                "rc = 0x%x\n", rc);
                goto out_destroy_fcp_wq;
        }
+
        lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                        "2592 USL RQ setup: hdr-rq-id=%d, dat-rq-id=%d "
                        "parent cq-id=%d\n",
@@ -6744,18 +6896,21 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
 out_destroy_fcp_wq:
        for (--fcp_wqidx; fcp_wqidx >= 0; fcp_wqidx--)
                lpfc_wq_destroy(phba, phba->sli4_hba.fcp_wq[fcp_wqidx]);
+out_destroy_els_wq:
        lpfc_wq_destroy(phba, phba->sli4_hba.els_wq);
 out_destroy_mbx_wq:
        lpfc_mq_destroy(phba, phba->sli4_hba.mbx_wq);
 out_destroy_fcp_cq:
        for (--fcp_cqidx; fcp_cqidx >= 0; fcp_cqidx--)
                lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_cqidx]);
+out_destroy_els_cq:
        lpfc_cq_destroy(phba, phba->sli4_hba.els_cq);
 out_destroy_mbx_cq:
        lpfc_cq_destroy(phba, phba->sli4_hba.mbx_cq);
 out_destroy_fp_eq:
        for (--fcp_eqidx; fcp_eqidx >= 0; fcp_eqidx--)
                lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_eqidx]);
+out_destroy_sp_eq:
        lpfc_eq_destroy(phba, phba->sli4_hba.sp_eq);
 out_error:
        return rc;
@@ -6792,11 +6947,18 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
        /* Unset ELS complete queue */
        lpfc_cq_destroy(phba, phba->sli4_hba.els_cq);
        /* Unset FCP response complete queue */
-       for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
-               lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]);
+       if (phba->sli4_hba.fcp_cq) {
+               fcp_qidx = 0;
+               do {
+                       lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]);
+               } while (++fcp_qidx < phba->cfg_fcp_eq_count);
+       }
        /* Unset fast-path event queue */
-       for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
-               lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_qidx]);
+       if (phba->sli4_hba.fp_eq) {
+               for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count;
+                    fcp_qidx++)
+                       lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_qidx]);
+       }
        /* Unset slow-path event queue */
        lpfc_eq_destroy(phba, phba->sli4_hba.sp_eq);
 }
@@ -7042,10 +7204,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
                         * the loop again.
                         */
                        for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
+                               msleep(10);
                                if (lpfc_readl(phba->sli4_hba.u.if_type2.
                                              STATUSregaddr, &reg_data.word0)) {
                                        rc = -ENODEV;
-                                       break;
+                                       goto out;
                                }
                                if (bf_get(lpfc_sliport_status_rdy, &reg_data))
                                        break;
@@ -7053,7 +7216,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
                                        reset_again++;
                                        break;
                                }
-                               msleep(10);
                        }
 
                        /*
@@ -7067,11 +7229,6 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
                        }
 
                        /* Detect any port errors. */
-                       if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
-                                &reg_data.word0)) {
-                               rc = -ENODEV;
-                               break;
-                       }
                        if ((bf_get(lpfc_sliport_status_err, &reg_data)) ||
                            (rdy_chk >= 1000)) {
                                phba->work_status[0] = readl(
@@ -7104,6 +7261,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
                break;
        }
 
+out:
        /* Catch the not-ready port failure after a port reset. */
        if (num_resets >= MAX_IF_TYPE_2_RESETS)
                rc = -ENODEV;
@@ -7151,12 +7309,13 @@ lpfc_sli4_send_nop_mbox_cmds(struct lpfc_hba *phba, uint32_t cnt)
        lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
                         LPFC_MBOX_OPCODE_NOP, length, LPFC_SLI4_MBX_EMBED);
 
-       mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
        for (cmdsent = 0; cmdsent < cnt; cmdsent++) {
                if (!phba->sli4_hba.intr_enable)
                        rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-               else
+               else {
+                       mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
                        rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+               }
                if (rc == MBX_TIMEOUT)
                        break;
                /* Check return status */
@@ -7338,22 +7497,25 @@ out:
 static void
 lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
 {
-       struct pci_dev *pdev;
-
-       /* Obtain PCI device reference */
-       if (!phba->pcidev)
-               return;
-       else
-               pdev = phba->pcidev;
-
-       /* Free coherent DMA memory allocated */
-
-       /* Unmap I/O memory space */
-       iounmap(phba->sli4_hba.drbl_regs_memmap_p);
-       iounmap(phba->sli4_hba.ctrl_regs_memmap_p);
-       iounmap(phba->sli4_hba.conf_regs_memmap_p);
+       uint32_t if_type;
+       if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
 
-       return;
+       switch (if_type) {
+       case LPFC_SLI_INTF_IF_TYPE_0:
+               iounmap(phba->sli4_hba.drbl_regs_memmap_p);
+               iounmap(phba->sli4_hba.ctrl_regs_memmap_p);
+               iounmap(phba->sli4_hba.conf_regs_memmap_p);
+               break;
+       case LPFC_SLI_INTF_IF_TYPE_2:
+               iounmap(phba->sli4_hba.conf_regs_memmap_p);
+               break;
+       case LPFC_SLI_INTF_IF_TYPE_1:
+       default:
+               dev_printk(KERN_ERR, &phba->pcidev->dev,
+                          "FATAL - unsupported SLI4 interface type - %d\n",
+                          if_type);
+               break;
+       }
 }
 
 /**
@@ -7976,6 +8138,7 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba)
 
        /* Reset SLI4 HBA FCoE function */
        lpfc_pci_function_reset(phba);
+       lpfc_sli4_queue_destroy(phba);
 
        return;
 }
@@ -8089,6 +8252,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
 
        /* Reset SLI4 HBA FCoE function */
        lpfc_pci_function_reset(phba);
+       lpfc_sli4_queue_destroy(phba);
 
        /* Stop the SLI4 device port */
        phba->pport->work_port_events = 0;
@@ -8122,7 +8286,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_PORT_CAPABILITIES);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
                rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
        }
 
@@ -8184,6 +8348,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        int rc;
        struct lpfc_mqe *mqe = &mboxq->u.mqe;
        struct lpfc_pc_sli4_params *sli4_params;
+       uint32_t mbox_tmo;
        int length;
        struct lpfc_sli4_parameters *mbx_sli4_parameters;
 
@@ -8202,9 +8367,10 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                         length, LPFC_SLI4_MBX_EMBED);
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-       else
-               rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
-                       lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
+       else {
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
+               rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
+       }
        if (unlikely(rc))
                return rc;
        sli4_params = &phba->sli4_hba.pc_sli4_params;
@@ -8273,11 +8439,8 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
 
        /* Perform generic PCI device enabling operation */
        error = lpfc_enable_pci_dev(phba);
-       if (error) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "1401 Failed to enable pci device.\n");
+       if (error)
                goto out_free_phba;
-       }
 
        /* Set up SLI API function jump table for PCI-device group-0 HBAs */
        error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_LP);
@@ -8324,6 +8487,9 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_free_iocb_list;
        }
 
+       /* Get the default values for Model Name and Description */
+       lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
+
        /* Create SCSI host to the physical port */
        error = lpfc_create_shost(phba);
        if (error) {
@@ -8887,16 +9053,17 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
        uint32_t offset = 0, temp_offset = 0;
 
        INIT_LIST_HEAD(&dma_buffer_list);
-       if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) ||
-           (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) ||
-           (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
-           (image->size != fw->size)) {
+       if ((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_NUM) ||
+           (bf_get_be32(lpfc_grp_hdr_file_type, image) !=
+            LPFC_FILE_TYPE_GROUP) ||
+           (bf_get_be32(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
+           (be32_to_cpu(image->size) != fw->size)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "3022 Invalid FW image found. "
-                               "Magic:%d Type:%x ID:%x\n",
-                               image->magic_number,
-                               bf_get(lpfc_grp_hdr_file_type, image),
-                               bf_get(lpfc_grp_hdr_id, image));
+                               "Magic:%x Type:%x ID:%x\n",
+                               be32_to_cpu(image->magic_number),
+                               bf_get_be32(lpfc_grp_hdr_file_type, image),
+                               bf_get_be32(lpfc_grp_hdr_id, image));
                return -EINVAL;
        }
        lpfc_decode_firmware_rev(phba, fwrev, 1);
@@ -8926,11 +9093,11 @@ lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw)
                while (offset < fw->size) {
                        temp_offset = offset;
                        list_for_each_entry(dmabuf, &dma_buffer_list, list) {
-                               if (offset + SLI4_PAGE_SIZE > fw->size) {
-                                       temp_offset += fw->size - offset;
+                               if (temp_offset + SLI4_PAGE_SIZE > fw->size) {
                                        memcpy(dmabuf->virt,
                                               fw->data + temp_offset,
-                                              fw->size - offset);
+                                              fw->size - temp_offset);
+                                       temp_offset = fw->size;
                                        break;
                                }
                                memcpy(dmabuf->virt, fw->data + temp_offset,
@@ -8986,7 +9153,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        uint32_t cfg_mode, intr_mode;
        int mcnt;
        int adjusted_fcp_eq_count;
-       int fcp_qidx;
        const struct firmware *fw;
        uint8_t file_name[16];
 
@@ -8997,11 +9163,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
 
        /* Perform generic PCI device enabling operation */
        error = lpfc_enable_pci_dev(phba);
-       if (error) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "1409 Failed to enable pci device.\n");
+       if (error)
                goto out_free_phba;
-       }
 
        /* Set up SLI API function jump table for PCI-device group-1 HBAs */
        error = lpfc_api_table_setup(phba, LPFC_PCI_DEV_OC);
@@ -9046,6 +9209,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        }
 
        INIT_LIST_HEAD(&phba->active_rrq_list);
+       INIT_LIST_HEAD(&phba->fcf.fcf_pri_list);
 
        /* Set up common device driver resources */
        error = lpfc_setup_driver_resource_phase2(phba);
@@ -9055,6 +9219,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_free_iocb_list;
        }
 
+       /* Get the default values for Model Name and Description */
+       lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
+
        /* Create SCSI host to the physical port */
        error = lpfc_create_shost(phba);
        if (error) {
@@ -9094,16 +9261,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                        adjusted_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1;
                else
                        adjusted_fcp_eq_count = phba->cfg_fcp_eq_count;
-               /* Free unused EQs */
-               for (fcp_qidx = adjusted_fcp_eq_count;
-                    fcp_qidx < phba->cfg_fcp_eq_count;
-                    fcp_qidx++) {
-                       lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]);
-                       /* do not delete the first fcp_cq */
-                       if (fcp_qidx)
-                               lpfc_sli4_queue_free(
-                                       phba->sli4_hba.fcp_cq[fcp_qidx]);
-               }
                phba->cfg_fcp_eq_count = adjusted_fcp_eq_count;
                /* Set up SLI-4 HBA */
                if (lpfc_sli4_hba_setup(phba)) {
@@ -9143,17 +9300,19 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        /* Perform post initialization setup */
        lpfc_post_init_setup(phba);
 
-       /* check for firmware upgrade or downgrade */
-       snprintf(file_name, 16, "%s.grp", phba->ModelName);
-       error = request_firmware(&fw, file_name, &phba->pcidev->dev);
-       if (!error) {
-               lpfc_write_firmware(phba, fw);
-               release_firmware(fw);
+       /* check for firmware upgrade or downgrade (if_type 2 only) */
+       if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+           LPFC_SLI_INTF_IF_TYPE_2) {
+               snprintf(file_name, 16, "%s.grp", phba->ModelName);
+               error = request_firmware(&fw, file_name, &phba->pcidev->dev);
+               if (!error) {
+                       lpfc_write_firmware(phba, fw);
+                       release_firmware(fw);
+               }
        }
 
        /* Check if there are static vports to be created. */
        lpfc_create_static_vport(phba);
-
        return 0;
 
 out_disable_intr:
@@ -9287,6 +9446,7 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg)
 
        /* Disable interrupt from device */
        lpfc_sli4_disable_intr(phba);
+       lpfc_sli4_queue_destroy(phba);
 
        /* Save device state to PCI config space */
        pci_save_state(pdev);
@@ -9416,6 +9576,7 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
 
        /* Disable interrupt and pci device */
        lpfc_sli4_disable_intr(phba);
+       lpfc_sli4_queue_destroy(phba);
        pci_disable_device(phba->pcidev);
 
        /* Flush all driver's outstanding SCSI I/Os as we are to reset */
index e3b790e5915624794284b5c2e420caee58fe6114..baf53e6c2bd15bfbbf8c25af5face63f1c9fe006 100644 (file)
@@ -36,6 +36,7 @@
 #define LOG_SECURITY   0x00008000      /* Security events */
 #define LOG_EVENT      0x00010000      /* CT,TEMP,DUMP, logging */
 #define LOG_FIP                0x00020000      /* FIP events */
+#define LOG_FCP_UNDER  0x00040000      /* FCP underruns errors */
 #define LOG_ALL_MSG    0xffffffff      /* LOG all messages */
 
 #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
index 83450cc5c4d3d0f722e214e4d09398501d491207..20336f09fb3cede76ddcc5e808a58d64c3e76b66 100644 (file)
@@ -1293,6 +1293,10 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                phba->sli_rev = LPFC_SLI_REV2;
        mb->un.varCfgPort.sli_mode = phba->sli_rev;
 
+       /* If this is an SLI3 port, configure async status notification. */
+       if (phba->sli_rev == LPFC_SLI_REV3)
+               mb->un.varCfgPort.casabt = 1;
+
        /* Now setup pcb */
        phba->pcb->type = TYPE_NATIVE_SLI2;
        phba->pcb->feature = FEATURE_INITIAL_SLI2;
@@ -1598,9 +1602,12 @@ lpfc_mbox_dev_check(struct lpfc_hba *phba)
  *    Timeout value to be used for the given mailbox command
  **/
 int
-lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
+lpfc_mbox_tmo_val(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
-       switch (cmd) {
+       MAILBOX_t *mbox = &mboxq->u.mb;
+       uint8_t subsys, opcode;
+
+       switch (mbox->mbxCommand) {
        case MBX_WRITE_NV:      /* 0x03 */
        case MBX_UPDATE_CFG:    /* 0x1B */
        case MBX_DOWN_LOAD:     /* 0x1C */
@@ -1610,6 +1617,28 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
        case MBX_LOAD_EXP_ROM:  /* 0x9C */
                return LPFC_MBOX_TMO_FLASH_CMD;
        case MBX_SLI4_CONFIG:   /* 0x9b */
+               subsys = lpfc_sli_config_mbox_subsys_get(phba, mboxq);
+               opcode = lpfc_sli_config_mbox_opcode_get(phba, mboxq);
+               if (subsys == LPFC_MBOX_SUBSYSTEM_COMMON) {
+                       switch (opcode) {
+                       case LPFC_MBOX_OPCODE_READ_OBJECT:
+                       case LPFC_MBOX_OPCODE_WRITE_OBJECT:
+                       case LPFC_MBOX_OPCODE_READ_OBJECT_LIST:
+                       case LPFC_MBOX_OPCODE_DELETE_OBJECT:
+                       case LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG:
+                       case LPFC_MBOX_OPCODE_GET_PROFILE_LIST:
+                       case LPFC_MBOX_OPCODE_SET_ACT_PROFILE:
+                       case LPFC_MBOX_OPCODE_SET_PROFILE_CONFIG:
+                       case LPFC_MBOX_OPCODE_GET_FACTORY_PROFILE_CONFIG:
+                               return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO;
+                       }
+               }
+               if (subsys == LPFC_MBOX_SUBSYSTEM_FCOE) {
+                       switch (opcode) {
+                       case LPFC_MBOX_OPCODE_FCOE_SET_FCLINK_SETTINGS:
+                               return LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO;
+                       }
+               }
                return LPFC_MBOX_SLI4_CONFIG_TMO;
        }
        return LPFC_MBOX_TMO;
@@ -1859,7 +1888,7 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
        }
 
        /* Complete the initialization for the particular Opcode. */
-       opcode = lpfc_sli4_mbox_opcode_get(phba, mbox);
+       opcode = lpfc_sli_config_mbox_opcode_get(phba, mbox);
        switch (opcode) {
        case LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT:
                if (emb == LPFC_SLI4_MBX_EMBED)
@@ -1886,23 +1915,56 @@ lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
 }
 
 /**
- * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command
+ * lpfc_sli_config_mbox_subsys_get - Get subsystem from a sli_config mbox cmd
  * @phba: pointer to lpfc hba data structure.
- * @mbox: pointer to lpfc mbox command.
+ * @mbox: pointer to lpfc mbox command queue entry.
+ *
+ * This routine gets the subsystem from a SLI4 specific SLI_CONFIG mailbox
+ * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if the
+ * sub-header is not present, subsystem LPFC_MBOX_SUBSYSTEM_NA (0x0) shall
+ * be returned.
+ **/
+uint8_t
+lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
+{
+       struct lpfc_mbx_sli4_config *sli4_cfg;
+       union lpfc_sli4_cfg_shdr *cfg_shdr;
+
+       if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG)
+               return LPFC_MBOX_SUBSYSTEM_NA;
+       sli4_cfg = &mbox->u.mqe.un.sli4_config;
+
+       /* For embedded mbox command, get opcode from embedded sub-header*/
+       if (bf_get(lpfc_mbox_hdr_emb, &sli4_cfg->header.cfg_mhdr)) {
+               cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr;
+               return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request);
+       }
+
+       /* For non-embedded mbox command, get opcode from first dma page */
+       if (unlikely(!mbox->sge_array))
+               return LPFC_MBOX_SUBSYSTEM_NA;
+       cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0];
+       return bf_get(lpfc_mbox_hdr_subsystem, &cfg_shdr->request);
+}
+
+/**
+ * lpfc_sli_config_mbox_opcode_get - Get opcode from a sli_config mbox cmd
+ * @phba: pointer to lpfc hba data structure.
+ * @mbox: pointer to lpfc mbox command queue entry.
  *
- * This routine gets the opcode from a SLI4 specific mailbox command for
- * sending IOCTL command. If the mailbox command is not MBX_SLI4_CONFIG
- * (0x9B) or if the IOCTL sub-header is not present, opcode 0x0 shall be
+ * This routine gets the opcode from a SLI4 specific SLI_CONFIG mailbox
+ * command. If the mailbox command is not MBX_SLI4_CONFIG (0x9B) or if
+ * the sub-header is not present, opcode LPFC_MBOX_OPCODE_NA (0x0) be
  * returned.
  **/
 uint8_t
-lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
+lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
 {
        struct lpfc_mbx_sli4_config *sli4_cfg;
        union lpfc_sli4_cfg_shdr *cfg_shdr;
 
        if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG)
-               return 0;
+               return LPFC_MBOX_OPCODE_NA;
        sli4_cfg = &mbox->u.mqe.un.sli4_config;
 
        /* For embedded mbox command, get opcode from embedded sub-header*/
@@ -1913,7 +1975,7 @@ lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
 
        /* For non-embedded mbox command, get opcode from first dma page */
        if (unlikely(!mbox->sge_array))
-               return 0;
+               return LPFC_MBOX_OPCODE_NA;
        cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0];
        return bf_get(lpfc_mbox_hdr_opcode, &cfg_shdr->request);
 }
@@ -2071,6 +2133,14 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
        reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam);
        reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
        bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID);
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX,
+                       "3134 Register VFI, mydid:x%x, fcfi:%d, "
+                       " vfi:%d, vpi:%d, fc_pname:%x%x\n",
+                       vport->fc_myDID,
+                       vport->phba->fcf.fcfi,
+                       vport->phba->sli4_hba.vfi_ids[vport->vfi],
+                       vport->phba->vpi_ids[vport->vpi],
+                       reg_vfi->wwn[0], reg_vfi->wwn[1]);
 }
 
 /**
@@ -2117,16 +2187,15 @@ lpfc_unreg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport)
 }
 
 /**
- * lpfc_dump_fcoe_param - Dump config region 23 to get FCoe parameters.
+ * lpfc_sli4_dump_cfg_rg23 - Dump sli4 port config region 23
  * @phba: pointer to the hba structure containing.
  * @mbox: pointer to lpfc mbox command to initialize.
  *
- * This function create a SLI4 dump mailbox command to dump FCoE
- * parameters stored in region 23.
+ * This function create a SLI4 dump mailbox command to dump configure
+ * region 23.
  **/
 int
-lpfc_dump_fcoe_param(struct lpfc_hba *phba,
-               struct lpfcMboxq *mbox)
+lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
 {
        struct lpfc_dmabuf *mp = NULL;
        MAILBOX_t *mb;
@@ -2140,9 +2209,9 @@ lpfc_dump_fcoe_param(struct lpfc_hba *phba,
 
        if (!mp || !mp->virt) {
                kfree(mp);
-               /* dump_fcoe_param failed to allocate memory */
+               /* dump config region 23 failed to allocate memory */
                lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
-                       "2569 lpfc_dump_fcoe_param: memory"
+                       "2569 lpfc dump config region 23: memory"
                        " allocation failed\n");
                return 1;
        }
index 10d5b5e4149999aeb493028c2ad0b6fba9885654..ade763d3930a7576e37b62285ab80b35869488aa 100644 (file)
@@ -389,7 +389,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba)
 {
        struct hbq_dmabuf *hbqbp;
 
-       hbqbp = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
+       hbqbp = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
        if (!hbqbp)
                return NULL;
 
@@ -441,7 +441,7 @@ lpfc_sli4_rb_alloc(struct lpfc_hba *phba)
 {
        struct hbq_dmabuf *dma_buf;
 
-       dma_buf = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
+       dma_buf = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
        if (!dma_buf)
                return NULL;
 
index 2ddd02f7c60336130e90f8a0eb5f0ba230484451..e8bb0055994316a790db82111163295efa5ba7be 100644 (file)
@@ -782,6 +782,14 @@ lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        return NLP_STE_FREED_NODE;
 }
 
+static uint32_t
+lpfc_device_recov_unused_node(struct lpfc_vport *vport,
+                       struct lpfc_nodelist *ndlp,
+                          void *arg, uint32_t evt)
+{
+       return ndlp->nlp_state;
+}
+
 static uint32_t
 lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                           void *arg, uint32_t evt)
@@ -2147,7 +2155,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
        lpfc_disc_illegal,              /* CMPL_ADISC      */
        lpfc_disc_illegal,              /* CMPL_REG_LOGIN  */
        lpfc_device_rm_unused_node,     /* DEVICE_RM       */
-       lpfc_disc_illegal,              /* DEVICE_RECOVERY */
+       lpfc_device_recov_unused_node,  /* DEVICE_RECOVERY */
 
        lpfc_rcv_plogi_plogi_issue,     /* RCV_PLOGI   PLOGI_ISSUE    */
        lpfc_rcv_prli_plogi_issue,      /* RCV_PRLI        */
index eadd241eeff113cffc7a893412c43662ba695828..9b2b1be7919b0fed025c2c585cfac0132856af6f 100644 (file)
@@ -58,6 +58,13 @@ static char *dif_op_str[] = {
        "SCSI_PROT_READ_PASS",
        "SCSI_PROT_WRITE_PASS",
 };
+
+struct scsi_dif_tuple {
+       __be16 guard_tag;       /* Checksum */
+       __be16 app_tag;         /* Opaque storage */
+       __be32 ref_tag;         /* Target LBA or indirect LBA */
+};
+
 static void
 lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
 static void
@@ -673,8 +680,10 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
 
                        rrq_empty = list_empty(&phba->active_rrq_list);
                        spin_unlock_irqrestore(&phba->hbalock, iflag);
-                       if (ndlp)
+                       if (ndlp) {
                                lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1);
+                               lpfc_sli4_abts_err_handler(phba, ndlp, axri);
+                       }
                        lpfc_release_scsi_buf_s4(phba, psb);
                        if (rrq_empty)
                                lpfc_worker_wake_up(phba);
@@ -1263,6 +1272,174 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
        return 0;
 }
 
+static inline unsigned
+lpfc_cmd_blksize(struct scsi_cmnd *sc)
+{
+       return sc->device->sector_size;
+}
+
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+/*
+ * Given a scsi cmnd, determine the BlockGuard tags to be used with it
+ * @sc: The SCSI command to examine
+ * @reftag: (out) BlockGuard reference tag for transmitted data
+ * @apptag: (out) BlockGuard application tag for transmitted data
+ * @new_guard (in) Value to replace CRC with if needed
+ *
+ * Returns (1) if error injection was performed, (0) otherwise
+ */
+static int
+lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+               uint32_t *reftag, uint16_t *apptag, uint32_t new_guard)
+{
+       struct scatterlist *sgpe; /* s/g prot entry */
+       struct scatterlist *sgde; /* s/g data entry */
+       struct scsi_dif_tuple *src;
+       uint32_t op = scsi_get_prot_op(sc);
+       uint32_t blksize;
+       uint32_t numblks;
+       sector_t lba;
+       int rc = 0;
+
+       if (op == SCSI_PROT_NORMAL)
+               return 0;
+
+       lba = scsi_get_lba(sc);
+       if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) {
+               blksize = lpfc_cmd_blksize(sc);
+               numblks = (scsi_bufflen(sc) + blksize - 1) / blksize;
+
+               /* Make sure we have the right LBA if one is specified */
+               if ((phba->lpfc_injerr_lba < lba) ||
+                       (phba->lpfc_injerr_lba >= (lba + numblks)))
+                       return 0;
+       }
+
+       sgpe = scsi_prot_sglist(sc);
+       sgde = scsi_sglist(sc);
+
+       /* Should we change the Reference Tag */
+       if (reftag) {
+               /*
+                * If we are SCSI_PROT_WRITE_STRIP, the protection data is
+                * being stripped from the wire, thus it doesn't matter.
+                */
+               if ((op == SCSI_PROT_WRITE_PASS) ||
+                       (op == SCSI_PROT_WRITE_INSERT)) {
+                       if (phba->lpfc_injerr_wref_cnt) {
+
+                               /* DEADBEEF will be the reftag on the wire */
+                               *reftag = 0xDEADBEEF;
+                               phba->lpfc_injerr_wref_cnt--;
+                               phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+                               rc = 1;
+
+                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                                       "9081 BLKGRD: Injecting reftag error: "
+                                       "write lba x%lx\n", (unsigned long)lba);
+                       }
+               } else {
+                       if (phba->lpfc_injerr_rref_cnt) {
+                               *reftag = 0xDEADBEEF;
+                               phba->lpfc_injerr_rref_cnt--;
+                               phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+                               rc = 1;
+
+                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                                       "9076 BLKGRD: Injecting reftag error: "
+                                       "read lba x%lx\n", (unsigned long)lba);
+                       }
+               }
+       }
+
+       /* Should we change the Application Tag */
+       if (apptag) {
+               /*
+                * If we are SCSI_PROT_WRITE_STRIP, the protection data is
+                * being stripped from the wire, thus it doesn't matter.
+                */
+               if ((op == SCSI_PROT_WRITE_PASS) ||
+                       (op == SCSI_PROT_WRITE_INSERT)) {
+                       if (phba->lpfc_injerr_wapp_cnt) {
+
+                               /* DEAD will be the apptag on the wire */
+                               *apptag = 0xDEAD;
+                               phba->lpfc_injerr_wapp_cnt--;
+                               phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+                               rc = 1;
+
+                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                                       "9077 BLKGRD: Injecting apptag error: "
+                                       "write lba x%lx\n", (unsigned long)lba);
+                       }
+               } else {
+                       if (phba->lpfc_injerr_rapp_cnt) {
+                               *apptag = 0xDEAD;
+                               phba->lpfc_injerr_rapp_cnt--;
+                               phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+                               rc = 1;
+
+                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                                       "9078 BLKGRD: Injecting apptag error: "
+                                       "read lba x%lx\n", (unsigned long)lba);
+                       }
+               }
+       }
+
+       /* Should we change the Guard Tag */
+
+       /*
+        * If we are SCSI_PROT_WRITE_INSERT, the protection data is
+        * being on the wire is being fully generated on the HBA.
+        * The host cannot change it or force an error.
+        */
+       if (((op == SCSI_PROT_WRITE_STRIP) ||
+               (op == SCSI_PROT_WRITE_PASS)) &&
+               phba->lpfc_injerr_wgrd_cnt) {
+               if (sgpe) {
+                       src = (struct scsi_dif_tuple *)sg_virt(sgpe);
+                       /*
+                        * Just inject an error in the first
+                        * prot block.
+                        */
+                       lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                               "9079 BLKGRD: Injecting guard error: "
+                               "write lba x%lx oldGuard x%x refTag x%x\n",
+                               (unsigned long)lba, src->guard_tag,
+                               src->ref_tag);
+
+                       src->guard_tag = (uint16_t)new_guard;
+                       phba->lpfc_injerr_wgrd_cnt--;
+                       phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+                       rc = 1;
+
+               } else {
+                       blksize = lpfc_cmd_blksize(sc);
+                       /*
+                        * Jump past the first data block
+                        * and inject an error in the
+                        * prot data. The prot data is already
+                        * embedded after the regular data.
+                        */
+                       src = (struct scsi_dif_tuple *)
+                                       (sg_virt(sgde) + blksize);
+
+                       lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                               "9080 BLKGRD: Injecting guard error: "
+                               "write lba x%lx oldGuard x%x refTag x%x\n",
+                               (unsigned long)lba, src->guard_tag,
+                               src->ref_tag);
+
+                       src->guard_tag = (uint16_t)new_guard;
+                       phba->lpfc_injerr_wgrd_cnt--;
+                       phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+                       rc = 1;
+               }
+       }
+       return rc;
+}
+#endif
+
 /*
  * Given a scsi cmnd, determine the BlockGuard opcodes to be used with it
  * @sc: The SCSI command to examine
@@ -1341,18 +1518,6 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        return ret;
 }
 
-struct scsi_dif_tuple {
-       __be16 guard_tag;       /* Checksum */
-       __be16 app_tag;         /* Opaque storage */
-       __be32 ref_tag;         /* Target LBA or indirect LBA */
-};
-
-static inline unsigned
-lpfc_cmd_blksize(struct scsi_cmnd *sc)
-{
-       return sc->device->sector_size;
-}
-
 /*
  * This function sets up buffer list for protection groups of
  * type LPFC_PG_TYPE_NO_DIF
@@ -1401,6 +1566,11 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        blksize = lpfc_cmd_blksize(sc);
        reftag = scsi_get_lba(sc) & 0xffffffff;
 
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       /* reftag is the only error we can inject here */
+       lpfc_bg_err_inject(phba, sc, &reftag, 0, 0);
+#endif
+
        /* setup PDE5 with what we have */
        pde5 = (struct lpfc_pde5 *) bpl;
        memset(pde5, 0, sizeof(struct lpfc_pde5));
@@ -1532,6 +1702,11 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        blksize = lpfc_cmd_blksize(sc);
        reftag = scsi_get_lba(sc) & 0xffffffff;
 
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       /* reftag / guard tag are the only errors we can inject here */
+       lpfc_bg_err_inject(phba, sc, &reftag, 0, 0xDEAD);
+#endif
+
        split_offset = 0;
        do {
                /* setup PDE5 with what we have */
@@ -1671,7 +1846,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                }
 
        } while (!alldone);
-
 out:
 
        return num_bde;
@@ -2075,6 +2249,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
                        else
                                bf_set(lpfc_sli4_sge_last, sgl, 0);
                        bf_set(lpfc_sli4_sge_offset, sgl, dma_offset);
+                       bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
                        sgl->word2 = cpu_to_le32(sgl->word2);
                        sgl->sge_len = cpu_to_le32(dma_len);
                        dma_offset += dma_len;
@@ -2325,8 +2500,9 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
        }
        lp = (uint32_t *)cmnd->sense_buffer;
 
-       if (!scsi_status && (resp_info & RESID_UNDER))
-               logit = LOG_FCP;
+       if (!scsi_status && (resp_info & RESID_UNDER) &&
+               vport->cfg_log_verbose & LOG_FCP_UNDER)
+               logit = LOG_FCP_UNDER;
 
        lpfc_printf_vlog(vport, KERN_WARNING, logit,
                         "9024 FCP command x%x failed: x%x SNS x%x x%x "
@@ -2342,7 +2518,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
        if (resp_info & RESID_UNDER) {
                scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
 
-               lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_UNDER,
                                 "9025 FCP Read Underrun, expected %d, "
                                 "residual %d Data: x%x x%x x%x\n",
                                 be32_to_cpu(fcpcmd->fcpDl),
@@ -2449,6 +2625,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        struct lpfc_fast_path_event *fast_path_evt;
        struct Scsi_Host *shost;
        uint32_t queue_depth, scsi_id;
+       uint32_t logit = LOG_FCP;
 
        /* Sanity check on return of outstanding command */
        if (!(lpfc_cmd->pCmd))
@@ -2470,16 +2647,22 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                        lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
                else if (lpfc_cmd->status >= IOSTAT_CNT)
                        lpfc_cmd->status = IOSTAT_DEFAULT;
-
-               lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
-                                "9030 FCP cmd x%x failed <%d/%d> "
-                                "status: x%x result: x%x Data: x%x x%x\n",
-                                cmd->cmnd[0],
-                                cmd->device ? cmd->device->id : 0xffff,
-                                cmd->device ? cmd->device->lun : 0xffff,
-                                lpfc_cmd->status, lpfc_cmd->result,
-                                pIocbOut->iocb.ulpContext,
-                                lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
+               if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR
+                       && !lpfc_cmd->fcp_rsp->rspStatus3
+                       && (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER)
+                       && !(phba->cfg_log_verbose & LOG_FCP_UNDER))
+                       logit = 0;
+               else
+                       logit = LOG_FCP | LOG_FCP_UNDER;
+               lpfc_printf_vlog(vport, KERN_WARNING, logit,
+                        "9030 FCP cmd x%x failed <%d/%d> "
+                        "status: x%x result: x%x Data: x%x x%x\n",
+                        cmd->cmnd[0],
+                        cmd->device ? cmd->device->id : 0xffff,
+                        cmd->device ? cmd->device->lun : 0xffff,
+                        lpfc_cmd->status, lpfc_cmd->result,
+                        pIocbOut->iocb.ulpContext,
+                        lpfc_cmd->cur_iocbq.iocb.ulpIoTag);
 
                switch (lpfc_cmd->status) {
                case IOSTAT_FCP_RSP_ERROR:
@@ -3054,10 +3237,20 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
                cmnd->result = err;
                goto out_fail_command;
        }
+       /*
+        * Do not let the mid-layer retry I/O too fast. If an I/O is retried
+        * without waiting a bit then indicate that the device is busy.
+        */
+       if (cmnd->retries &&
+           time_before(jiffies, (cmnd->jiffies_at_alloc +
+                                 msecs_to_jiffies(LPFC_RETRY_PAUSE *
+                                                  cmnd->retries))))
+               return SCSI_MLQUEUE_DEVICE_BUSY;
        ndlp = rdata->pnode;
 
-       if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
-               scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) {
+       if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) &&
+               (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) ||
+               (phba->sli_rev == LPFC_SLI_REV4))) {
 
                lpfc_printf_log(phba, KERN_ERR, LOG_BG,
                                "9058 BLKGRD: ERROR: rcvd protected cmd:%02x"
@@ -3548,7 +3741,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
        unsigned tgt_id = cmnd->device->id;
        unsigned int lun_id = cmnd->device->lun;
        struct lpfc_scsi_event_header scsi_event;
-       int status;
+       int status = SUCCESS;
 
        if (!rdata) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -3615,7 +3808,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
        unsigned tgt_id = cmnd->device->id;
        unsigned int lun_id = cmnd->device->lun;
        struct lpfc_scsi_event_header scsi_event;
-       int status;
+       int status = SUCCESS;
 
        if (!rdata) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -3680,7 +3873,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
        struct lpfc_nodelist *ndlp = NULL;
        struct lpfc_scsi_event_header scsi_event;
        int match;
-       int ret = SUCCESS, status, i;
+       int ret = SUCCESS, status = SUCCESS, i;
 
        scsi_event.event_type = FC_REG_SCSI_EVENT;
        scsi_event.subcategory = LPFC_EVENT_BUSRESET;
@@ -3691,9 +3884,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
        fc_host_post_vendor_event(shost, fc_get_event_number(),
                sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
 
-       ret = fc_block_scsi_eh(cmnd);
-       if (ret)
-               return ret;
+       status = fc_block_scsi_eh(cmnd);
+       if (status)
+               return status;
 
        /*
         * Since the driver manages a single bus device, reset all
@@ -3824,6 +4017,7 @@ lpfc_slave_alloc(struct scsi_device *sdev)
  *
  * This routine configures following items
  *   - Tag command queuing support for @sdev if supported.
+ *   - Dev loss time out value of fc_rport.
  *   - Enable SLI polling for fcp ring if ENABLE_FCP_RING_POLLING flag is set.
  *
  * Return codes:
@@ -3834,12 +4028,21 @@ lpfc_slave_configure(struct scsi_device *sdev)
 {
        struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
        struct lpfc_hba   *phba = vport->phba;
+       struct fc_rport   *rport = starget_to_rport(sdev->sdev_target);
 
        if (sdev->tagged_supported)
                scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth);
        else
                scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth);
 
+       /*
+        * Initialize the fc transport attributes for the target
+        * containing this scsi device.  Also note that the driver's
+        * target pointer is stored in the starget_data for the
+        * driver's sysfs entry point functions.
+        */
+       rport->dev_loss_tmo = vport->cfg_devloss_tmo;
+
        if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
                lpfc_sli_handle_fast_ring_event(phba,
                        &phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
index ce645b20a6ad3eda03f03c5ccc1059406476d1f2..669f965e071bdeef65b15fc3977e3f9a0164fb38 100644 (file)
@@ -153,5 +153,5 @@ struct lpfc_scsi_buf {
 
 #define LPFC_SCSI_DMA_EXT_SIZE 264
 #define LPFC_BPL_SIZE          1024
-
+#define LPFC_RETRY_PAUSE       300
 #define MDAC_DIRECT_CMD                  0x22
index 5b28ea1d72c518e589b5d833da6e1924f507f1c9..d3b0474c0411092a0746b9c7253dd61c14cbc286 100644 (file)
@@ -89,15 +89,20 @@ lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
 static uint32_t
 lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
 {
-       union lpfc_wqe *temp_wqe = q->qe[q->host_index].wqe;
+       union lpfc_wqe *temp_wqe;
        struct lpfc_register doorbell;
        uint32_t host_index;
 
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return -ENOMEM;
+       temp_wqe = q->qe[q->host_index].wqe;
+
        /* If the host has not yet processed the next entry then we are done */
        if (((q->host_index + 1) % q->entry_count) == q->hba_index)
                return -ENOMEM;
        /* set consumption flag every once in a while */
-       if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL))
+       if (!((q->host_index + 1) % q->entry_repost))
                bf_set(wqe_wqec, &wqe->generic.wqe_com, 1);
        if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
                bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
@@ -134,6 +139,10 @@ lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index)
 {
        uint32_t released = 0;
 
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return 0;
+
        if (q->hba_index == index)
                return 0;
        do {
@@ -158,10 +167,15 @@ lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index)
 static uint32_t
 lpfc_sli4_mq_put(struct lpfc_queue *q, struct lpfc_mqe *mqe)
 {
-       struct lpfc_mqe *temp_mqe = q->qe[q->host_index].mqe;
+       struct lpfc_mqe *temp_mqe;
        struct lpfc_register doorbell;
        uint32_t host_index;
 
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return -ENOMEM;
+       temp_mqe = q->qe[q->host_index].mqe;
+
        /* If the host has not yet processed the next entry then we are done */
        if (((q->host_index + 1) % q->entry_count) == q->hba_index)
                return -ENOMEM;
@@ -195,6 +209,10 @@ lpfc_sli4_mq_put(struct lpfc_queue *q, struct lpfc_mqe *mqe)
 static uint32_t
 lpfc_sli4_mq_release(struct lpfc_queue *q)
 {
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return 0;
+
        /* Clear the mailbox pointer for completion */
        q->phba->mbox = NULL;
        q->hba_index = ((q->hba_index + 1) % q->entry_count);
@@ -213,7 +231,12 @@ lpfc_sli4_mq_release(struct lpfc_queue *q)
 static struct lpfc_eqe *
 lpfc_sli4_eq_get(struct lpfc_queue *q)
 {
-       struct lpfc_eqe *eqe = q->qe[q->hba_index].eqe;
+       struct lpfc_eqe *eqe;
+
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return NULL;
+       eqe = q->qe[q->hba_index].eqe;
 
        /* If the next EQE is not valid then we are done */
        if (!bf_get_le32(lpfc_eqe_valid, eqe))
@@ -248,6 +271,10 @@ lpfc_sli4_eq_release(struct lpfc_queue *q, bool arm)
        struct lpfc_eqe *temp_eqe;
        struct lpfc_register doorbell;
 
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return 0;
+
        /* while there are valid entries */
        while (q->hba_index != q->host_index) {
                temp_eqe = q->qe[q->host_index].eqe;
@@ -288,6 +315,10 @@ lpfc_sli4_cq_get(struct lpfc_queue *q)
 {
        struct lpfc_cqe *cqe;
 
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return NULL;
+
        /* If the next CQE is not valid then we are done */
        if (!bf_get_le32(lpfc_cqe_valid, q->qe[q->hba_index].cqe))
                return NULL;
@@ -322,6 +353,9 @@ lpfc_sli4_cq_release(struct lpfc_queue *q, bool arm)
        struct lpfc_cqe *temp_qe;
        struct lpfc_register doorbell;
 
+       /* sanity check on queue memory */
+       if (unlikely(!q))
+               return 0;
        /* while there are valid entries */
        while (q->hba_index != q->host_index) {
                temp_qe = q->qe[q->host_index].cqe;
@@ -359,11 +393,17 @@ static int
 lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
                 struct lpfc_rqe *hrqe, struct lpfc_rqe *drqe)
 {
-       struct lpfc_rqe *temp_hrqe = hq->qe[hq->host_index].rqe;
-       struct lpfc_rqe *temp_drqe = dq->qe[dq->host_index].rqe;
+       struct lpfc_rqe *temp_hrqe;
+       struct lpfc_rqe *temp_drqe;
        struct lpfc_register doorbell;
        int put_index = hq->host_index;
 
+       /* sanity check on queue memory */
+       if (unlikely(!hq) || unlikely(!dq))
+               return -ENOMEM;
+       temp_hrqe = hq->qe[hq->host_index].rqe;
+       temp_drqe = dq->qe[dq->host_index].rqe;
+
        if (hq->type != LPFC_HRQ || dq->type != LPFC_DRQ)
                return -EINVAL;
        if (hq->host_index != dq->host_index)
@@ -379,10 +419,10 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
        dq->host_index = ((dq->host_index + 1) % dq->entry_count);
 
        /* Ring The Header Receive Queue Doorbell */
-       if (!(hq->host_index % LPFC_RQ_POST_BATCH)) {
+       if (!(hq->host_index % hq->entry_repost)) {
                doorbell.word0 = 0;
                bf_set(lpfc_rq_doorbell_num_posted, &doorbell,
-                      LPFC_RQ_POST_BATCH);
+                      hq->entry_repost);
                bf_set(lpfc_rq_doorbell_id, &doorbell, hq->queue_id);
                writel(doorbell.word0, hq->phba->sli4_hba.RQDBregaddr);
        }
@@ -402,6 +442,10 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
 static uint32_t
 lpfc_sli4_rq_release(struct lpfc_queue *hq, struct lpfc_queue *dq)
 {
+       /* sanity check on queue memory */
+       if (unlikely(!hq) || unlikely(!dq))
+               return 0;
+
        if ((hq->type != LPFC_HRQ) || (dq->type != LPFC_DRQ))
                return 0;
        hq->hba_index = ((hq->hba_index + 1) % hq->entry_count);
@@ -1864,7 +1908,7 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
 {
        if (phba->sli_rev == LPFC_SLI_REV4)
                return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
-                                        lpfc_hbq_defs[qno]->entry_count);
+                                       lpfc_hbq_defs[qno]->entry_count);
        else
                return lpfc_sli_hbqbuf_fill_hbqs(phba, qno,
                                         lpfc_hbq_defs[qno]->init_count);
@@ -2200,10 +2244,13 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
                        /* Unknown mailbox command compl */
                        lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
                                        "(%d):0323 Unknown Mailbox command "
-                                       "x%x (x%x) Cmpl\n",
+                                       "x%x (x%x/x%x) Cmpl\n",
                                        pmb->vport ? pmb->vport->vpi : 0,
                                        pmbox->mbxCommand,
-                                       lpfc_sli4_mbox_opcode_get(phba, pmb));
+                                       lpfc_sli_config_mbox_subsys_get(phba,
+                                                                       pmb),
+                                       lpfc_sli_config_mbox_opcode_get(phba,
+                                                                       pmb));
                        phba->link_state = LPFC_HBA_ERROR;
                        phba->work_hs = HS_FFER3;
                        lpfc_handle_eratt(phba);
@@ -2215,17 +2262,19 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
                        if (pmbox->mbxStatus == MBXERR_NO_RESOURCES) {
                                /* Mbox cmd cmpl error - RETRYing */
                                lpfc_printf_log(phba, KERN_INFO,
-                                               LOG_MBOX | LOG_SLI,
-                                               "(%d):0305 Mbox cmd cmpl "
-                                               "error - RETRYing Data: x%x "
-                                               "(x%x) x%x x%x x%x\n",
-                                               pmb->vport ? pmb->vport->vpi :0,
-                                               pmbox->mbxCommand,
-                                               lpfc_sli4_mbox_opcode_get(phba,
-                                                                         pmb),
-                                               pmbox->mbxStatus,
-                                               pmbox->un.varWords[0],
-                                               pmb->vport->port_state);
+                                       LOG_MBOX | LOG_SLI,
+                                       "(%d):0305 Mbox cmd cmpl "
+                                       "error - RETRYing Data: x%x "
+                                       "(x%x/x%x) x%x x%x x%x\n",
+                                       pmb->vport ? pmb->vport->vpi : 0,
+                                       pmbox->mbxCommand,
+                                       lpfc_sli_config_mbox_subsys_get(phba,
+                                                                       pmb),
+                                       lpfc_sli_config_mbox_opcode_get(phba,
+                                                                       pmb),
+                                       pmbox->mbxStatus,
+                                       pmbox->un.varWords[0],
+                                       pmb->vport->port_state);
                                pmbox->mbxStatus = 0;
                                pmbox->mbxOwner = OWN_HOST;
                                rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
@@ -2236,11 +2285,12 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
 
                /* Mailbox cmd <cmd> Cmpl <cmpl> */
                lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
-                               "(%d):0307 Mailbox cmd x%x (x%x) Cmpl x%p "
+                               "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p "
                                "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
                                pmb->vport ? pmb->vport->vpi : 0,
                                pmbox->mbxCommand,
-                               lpfc_sli4_mbox_opcode_get(phba, pmb),
+                               lpfc_sli_config_mbox_subsys_get(phba, pmb),
+                               lpfc_sli_config_mbox_opcode_get(phba, pmb),
                                pmb->mbox_cmpl,
                                *((uint32_t *) pmbox),
                                pmbox->un.varWords[0],
@@ -3569,8 +3619,8 @@ lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
  * lpfc_reset_barrier - Make HBA ready for HBA reset
  * @phba: Pointer to HBA context object.
  *
- * This function is called before resetting an HBA. This
- * function requests HBA to quiesce DMAs before a reset.
+ * This function is called before resetting an HBA. This function is called
+ * with hbalock held and requests HBA to quiesce DMAs before a reset.
  **/
 void lpfc_reset_barrier(struct lpfc_hba *phba)
 {
@@ -3845,7 +3895,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
 {
        struct lpfc_sli *psli = &phba->sli;
        uint16_t cfg_value;
-       uint8_t qindx;
 
        /* Reset HBA */
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
@@ -3861,19 +3910,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
        spin_lock_irq(&phba->hbalock);
        psli->sli_flag &= ~(LPFC_PROCESS_LA);
        phba->fcf.fcf_flag = 0;
-       /* Clean up the child queue list for the CQs */
-       list_del_init(&phba->sli4_hba.mbx_wq->list);
-       list_del_init(&phba->sli4_hba.els_wq->list);
-       list_del_init(&phba->sli4_hba.hdr_rq->list);
-       list_del_init(&phba->sli4_hba.dat_rq->list);
-       list_del_init(&phba->sli4_hba.mbx_cq->list);
-       list_del_init(&phba->sli4_hba.els_cq->list);
-       for (qindx = 0; qindx < phba->cfg_fcp_wq_count; qindx++)
-               list_del_init(&phba->sli4_hba.fcp_wq[qindx]->list);
-       qindx = 0;
-       do
-               list_del_init(&phba->sli4_hba.fcp_cq[qindx]->list);
-       while (++qindx < phba->cfg_fcp_eq_count);
        spin_unlock_irq(&phba->hbalock);
 
        /* Now physically reset the device */
@@ -3886,6 +3922,7 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
                              ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
 
        /* Perform FCoE PCI function reset */
+       lpfc_sli4_queue_destroy(phba);
        lpfc_pci_function_reset(phba);
 
        /* Restore PCI cmd register */
@@ -4333,6 +4370,11 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
                        phba->sli.sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
                        spin_unlock_irq(&phba->hbalock);
                        done = 1;
+
+                       if ((pmb->u.mb.un.varCfgPort.casabt == 1) &&
+                           (pmb->u.mb.un.varCfgPort.gasabt == 0))
+                               lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+                                       "3110 Port did not grant ASABT\n");
                }
        }
        if (!done) {
@@ -4545,9 +4587,9 @@ lpfc_sli_hba_setup_error:
  * data structure.
  **/
 static int
-lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba,
-               LPFC_MBOXQ_t *mboxq)
+lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba)
 {
+       LPFC_MBOXQ_t *mboxq;
        struct lpfc_dmabuf *mp;
        struct lpfc_mqe *mqe;
        uint32_t data_length;
@@ -4559,10 +4601,16 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba,
        phba->fc_map[1] = LPFC_FCOE_FCF_MAP1;
        phba->fc_map[2] = LPFC_FCOE_FCF_MAP2;
 
-       mqe = &mboxq->u.mqe;
-       if (lpfc_dump_fcoe_param(phba, mboxq))
+       mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mboxq)
                return -ENOMEM;
 
+       mqe = &mboxq->u.mqe;
+       if (lpfc_sli4_dump_cfg_rg23(phba, mboxq)) {
+               rc = -ENOMEM;
+               goto out_free_mboxq;
+       }
+
        mp = (struct lpfc_dmabuf *) mboxq->context1;
        rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
 
@@ -4590,19 +4638,25 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba,
        if (rc) {
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
-               return -EIO;
+               rc = -EIO;
+               goto out_free_mboxq;
        }
        data_length = mqe->un.mb_words[5];
        if (data_length > DMP_RGN23_SIZE) {
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
                kfree(mp);
-               return -EIO;
+               rc = -EIO;
+               goto out_free_mboxq;
        }
 
        lpfc_parse_fcoe_conf(phba, mp->virt, data_length);
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
-       return 0;
+       rc = 0;
+
+out_free_mboxq:
+       mempool_free(mboxq, phba->mbox_mem_pool);
+       return rc;
 }
 
 /**
@@ -4685,6 +4739,152 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
        return 0;
 }
 
+/**
+ * lpfc_sli4_retrieve_pport_name - Retrieve SLI4 device physical port name
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine retrieves SLI4 device physical port name this PCI function
+ * is attached to.
+ *
+ * Return codes
+ *      0 - sucessful
+ *      otherwise - failed to retrieve physical port name
+ **/
+static int
+lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba)
+{
+       LPFC_MBOXQ_t *mboxq;
+       struct lpfc_mbx_get_cntl_attributes *mbx_cntl_attr;
+       struct lpfc_controller_attribute *cntl_attr;
+       struct lpfc_mbx_get_port_name *get_port_name;
+       void *virtaddr = NULL;
+       uint32_t alloclen, reqlen;
+       uint32_t shdr_status, shdr_add_status;
+       union lpfc_sli4_cfg_shdr *shdr;
+       char cport_name = 0;
+       int rc;
+
+       /* We assume nothing at this point */
+       phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_INVAL;
+       phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_NON;
+
+       mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mboxq)
+               return -ENOMEM;
+       /* obtain link type and link number via READ_CONFIG */
+       phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_INVAL;
+       lpfc_sli4_read_config(phba);
+       if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL)
+               goto retrieve_ppname;
+
+       /* obtain link type and link number via COMMON_GET_CNTL_ATTRIBUTES */
+       reqlen = sizeof(struct lpfc_mbx_get_cntl_attributes);
+       alloclen = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+                       LPFC_MBOX_OPCODE_GET_CNTL_ATTRIBUTES, reqlen,
+                       LPFC_SLI4_MBX_NEMBED);
+       if (alloclen < reqlen) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "3084 Allocated DMA memory size (%d) is "
+                               "less than the requested DMA memory size "
+                               "(%d)\n", alloclen, reqlen);
+               rc = -ENOMEM;
+               goto out_free_mboxq;
+       }
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       virtaddr = mboxq->sge_array->addr[0];
+       mbx_cntl_attr = (struct lpfc_mbx_get_cntl_attributes *)virtaddr;
+       shdr = &mbx_cntl_attr->cfg_shdr;
+       shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+       shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+       if (shdr_status || shdr_add_status || rc) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                               "3085 Mailbox x%x (x%x/x%x) failed, "
+                               "rc:x%x, status:x%x, add_status:x%x\n",
+                               bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+                               lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                               lpfc_sli_config_mbox_opcode_get(phba, mboxq),
+                               rc, shdr_status, shdr_add_status);
+               rc = -ENXIO;
+               goto out_free_mboxq;
+       }
+       cntl_attr = &mbx_cntl_attr->cntl_attr;
+       phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL;
+       phba->sli4_hba.lnk_info.lnk_tp =
+               bf_get(lpfc_cntl_attr_lnk_type, cntl_attr);
+       phba->sli4_hba.lnk_info.lnk_no =
+               bf_get(lpfc_cntl_attr_lnk_numb, cntl_attr);
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "3086 lnk_type:%d, lnk_numb:%d\n",
+                       phba->sli4_hba.lnk_info.lnk_tp,
+                       phba->sli4_hba.lnk_info.lnk_no);
+
+retrieve_ppname:
+       lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+               LPFC_MBOX_OPCODE_GET_PORT_NAME,
+               sizeof(struct lpfc_mbx_get_port_name) -
+               sizeof(struct lpfc_sli4_cfg_mhdr),
+               LPFC_SLI4_MBX_EMBED);
+       get_port_name = &mboxq->u.mqe.un.get_port_name;
+       shdr = (union lpfc_sli4_cfg_shdr *)&get_port_name->header.cfg_shdr;
+       bf_set(lpfc_mbox_hdr_version, &shdr->request, LPFC_OPCODE_VERSION_1);
+       bf_set(lpfc_mbx_get_port_name_lnk_type, &get_port_name->u.request,
+               phba->sli4_hba.lnk_info.lnk_tp);
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+       shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
+       if (shdr_status || shdr_add_status || rc) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                               "3087 Mailbox x%x (x%x/x%x) failed: "
+                               "rc:x%x, status:x%x, add_status:x%x\n",
+                               bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+                               lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                               lpfc_sli_config_mbox_opcode_get(phba, mboxq),
+                               rc, shdr_status, shdr_add_status);
+               rc = -ENXIO;
+               goto out_free_mboxq;
+       }
+       switch (phba->sli4_hba.lnk_info.lnk_no) {
+       case LPFC_LINK_NUMBER_0:
+               cport_name = bf_get(lpfc_mbx_get_port_name_name0,
+                               &get_port_name->u.response);
+               phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+               break;
+       case LPFC_LINK_NUMBER_1:
+               cport_name = bf_get(lpfc_mbx_get_port_name_name1,
+                               &get_port_name->u.response);
+               phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+               break;
+       case LPFC_LINK_NUMBER_2:
+               cport_name = bf_get(lpfc_mbx_get_port_name_name2,
+                               &get_port_name->u.response);
+               phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+               break;
+       case LPFC_LINK_NUMBER_3:
+               cport_name = bf_get(lpfc_mbx_get_port_name_name3,
+                               &get_port_name->u.response);
+               phba->sli4_hba.pport_name_sta = LPFC_SLI4_PPNAME_GET;
+               break;
+       default:
+               break;
+       }
+
+       if (phba->sli4_hba.pport_name_sta == LPFC_SLI4_PPNAME_GET) {
+               phba->Port[0] = cport_name;
+               phba->Port[1] = '\0';
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                               "3091 SLI get port name: %s\n", phba->Port);
+       }
+
+out_free_mboxq:
+       if (rc != MBX_TIMEOUT) {
+               if (bf_get(lpfc_mqe_command, &mboxq->u.mqe) == MBX_SLI4_CONFIG)
+                       lpfc_sli4_mbox_cmd_free(phba, mboxq);
+               else
+                       mempool_free(mboxq, phba->mbox_mem_pool);
+       }
+       return rc;
+}
+
 /**
  * lpfc_sli4_arm_cqeq_intr - Arm sli-4 device completion and event queues
  * @phba: pointer to lpfc hba data structure.
@@ -4700,24 +4900,34 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
        lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM);
        lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM);
        fcp_eqidx = 0;
-       do
-               lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx],
-                                    LPFC_QUEUE_REARM);
-       while (++fcp_eqidx < phba->cfg_fcp_eq_count);
+       if (phba->sli4_hba.fcp_cq) {
+               do
+                       lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx],
+                                            LPFC_QUEUE_REARM);
+               while (++fcp_eqidx < phba->cfg_fcp_eq_count);
+       }
        lpfc_sli4_eq_release(phba->sli4_hba.sp_eq, LPFC_QUEUE_REARM);
-       for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++)
-               lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx],
-                                    LPFC_QUEUE_REARM);
+       if (phba->sli4_hba.fp_eq) {
+               for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count;
+                    fcp_eqidx++)
+                       lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx],
+                                            LPFC_QUEUE_REARM);
+       }
 }
 
 /**
  * lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count.
  * @phba: Pointer to HBA context object.
  * @type: The resource extent type.
+ * @extnt_count: buffer to hold port available extent count.
+ * @extnt_size: buffer to hold element count per extent.
  *
- * This function allocates all SLI4 resource identifiers.
+ * This function calls the port and retrievs the number of available
+ * extents and their size for a particular extent type.
+ *
+ * Returns: 0 if successful.  Nonzero otherwise.
  **/
-static int
+int
 lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
                               uint16_t *extnt_count, uint16_t *extnt_size)
 {
@@ -4749,7 +4959,7 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
        }
        if (unlikely(rc)) {
@@ -4894,7 +5104,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
                                     req_len, *emb);
        if (alloc_len < req_len) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                       "9000 Allocated DMA memory size (x%x) is "
+                       "2982 Allocated DMA memory size (x%x) is "
                        "less than the requested DMA memory "
                        "size (x%x)\n", alloc_len, req_len);
                return -ENOMEM;
@@ -4906,7 +5116,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
        }
 
@@ -5189,7 +5399,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox_tmo);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
        }
        if (unlikely(rc)) {
@@ -5277,6 +5487,8 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
        uint16_t count, base;
        unsigned long longs;
 
+       if (!phba->sli4_hba.rpi_hdrs_in_use)
+               phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.max_rpi;
        if (phba->sli4_hba.extents_in_use) {
                /*
                 * The port supports resource extents. The XRI, VPI, VFI, RPI
@@ -5358,9 +5570,10 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
                 * need any action - just exit.
                 */
                if (bf_get(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags) ==
-                   LPFC_IDX_RSRC_RDY)
-                       return 0;
-
+                   LPFC_IDX_RSRC_RDY) {
+                       lpfc_sli4_dealloc_resource_identifiers(phba);
+                       lpfc_sli4_remove_rpis(phba);
+               }
                /* RPIs. */
                count = phba->sli4_hba.max_cfg_param.max_rpi;
                base = phba->sli4_hba.max_cfg_param.rpi_base;
@@ -5507,6 +5720,154 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
        return 0;
 }
 
+/**
+ * lpfc_sli4_get_allocated_extnts - Get the port's allocated extents.
+ * @phba: Pointer to HBA context object.
+ * @type: The resource extent type.
+ * @extnt_count: buffer to hold port extent count response
+ * @extnt_size: buffer to hold port extent size response.
+ *
+ * This function calls the port to read the host allocated extents
+ * for a particular type.
+ **/
+int
+lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type,
+                              uint16_t *extnt_cnt, uint16_t *extnt_size)
+{
+       bool emb;
+       int rc = 0;
+       uint16_t curr_blks = 0;
+       uint32_t req_len, emb_len;
+       uint32_t alloc_len, mbox_tmo;
+       struct list_head *blk_list_head;
+       struct lpfc_rsrc_blks *rsrc_blk;
+       LPFC_MBOXQ_t *mbox;
+       void *virtaddr = NULL;
+       struct lpfc_mbx_nembed_rsrc_extent *n_rsrc;
+       struct lpfc_mbx_alloc_rsrc_extents *rsrc_ext;
+       union  lpfc_sli4_cfg_shdr *shdr;
+
+       switch (type) {
+       case LPFC_RSC_TYPE_FCOE_VPI:
+               blk_list_head = &phba->lpfc_vpi_blk_list;
+               break;
+       case LPFC_RSC_TYPE_FCOE_XRI:
+               blk_list_head = &phba->sli4_hba.lpfc_xri_blk_list;
+               break;
+       case LPFC_RSC_TYPE_FCOE_VFI:
+               blk_list_head = &phba->sli4_hba.lpfc_vfi_blk_list;
+               break;
+       case LPFC_RSC_TYPE_FCOE_RPI:
+               blk_list_head = &phba->sli4_hba.lpfc_rpi_blk_list;
+               break;
+       default:
+               return -EIO;
+       }
+
+       /* Count the number of extents currently allocatd for this type. */
+       list_for_each_entry(rsrc_blk, blk_list_head, list) {
+               if (curr_blks == 0) {
+                       /*
+                        * The GET_ALLOCATED mailbox does not return the size,
+                        * just the count.  The size should be just the size
+                        * stored in the current allocated block and all sizes
+                        * for an extent type are the same so set the return
+                        * value now.
+                        */
+                       *extnt_size = rsrc_blk->rsrc_size;
+               }
+               curr_blks++;
+       }
+
+       /* Calculate the total requested length of the dma memory. */
+       req_len = curr_blks * sizeof(uint16_t);
+
+       /*
+        * Calculate the size of an embedded mailbox.  The uint32_t
+        * accounts for extents-specific word.
+        */
+       emb_len = sizeof(MAILBOX_t) - sizeof(struct mbox_header) -
+               sizeof(uint32_t);
+
+       /*
+        * Presume the allocation and response will fit into an embedded
+        * mailbox.  If not true, reconfigure to a non-embedded mailbox.
+        */
+       emb = LPFC_SLI4_MBX_EMBED;
+       req_len = emb_len;
+       if (req_len > emb_len) {
+               req_len = curr_blks * sizeof(uint16_t) +
+                       sizeof(union lpfc_sli4_cfg_shdr) +
+                       sizeof(uint32_t);
+               emb = LPFC_SLI4_MBX_NEMBED;
+       }
+
+       mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mbox)
+               return -ENOMEM;
+       memset(mbox, 0, sizeof(LPFC_MBOXQ_t));
+
+       alloc_len = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
+                                    LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT,
+                                    req_len, emb);
+       if (alloc_len < req_len) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "2983 Allocated DMA memory size (x%x) is "
+                       "less than the requested DMA memory "
+                       "size (x%x)\n", alloc_len, req_len);
+               rc = -ENOMEM;
+               goto err_exit;
+       }
+       rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, curr_blks, type, emb);
+       if (unlikely(rc)) {
+               rc = -EIO;
+               goto err_exit;
+       }
+
+       if (!phba->sli4_hba.intr_enable)
+               rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
+       else {
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
+               rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
+       }
+
+       if (unlikely(rc)) {
+               rc = -EIO;
+               goto err_exit;
+       }
+
+       /*
+        * Figure out where the response is located.  Then get local pointers
+        * to the response data.  The port does not guarantee to respond to
+        * all extents counts request so update the local variable with the
+        * allocated count from the port.
+        */
+       if (emb == LPFC_SLI4_MBX_EMBED) {
+               rsrc_ext = &mbox->u.mqe.un.alloc_rsrc_extents;
+               shdr = &rsrc_ext->header.cfg_shdr;
+               *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, &rsrc_ext->u.rsp);
+       } else {
+               virtaddr = mbox->sge_array->addr[0];
+               n_rsrc = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr;
+               shdr = &n_rsrc->cfg_shdr;
+               *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, n_rsrc);
+       }
+
+       if (bf_get(lpfc_mbox_hdr_status, &shdr->response)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+                       "2984 Failed to read allocated resources "
+                       "for type %d - Status 0x%x Add'l Status 0x%x.\n",
+                       type,
+                       bf_get(lpfc_mbox_hdr_status, &shdr->response),
+                       bf_get(lpfc_mbox_hdr_add_status, &shdr->response));
+               rc = -EIO;
+               goto err_exit;
+       }
+ err_exit:
+       lpfc_sli4_mbox_cmd_free(phba, mbox);
+       return rc;
+}
+
 /**
  * lpfc_sli4_hba_setup - SLI4 device intialization PCI function
  * @phba: Pointer to HBA context object.
@@ -5552,14 +5913,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
        if (!mboxq)
                return -ENOMEM;
 
-       /*
-        * Continue initialization with default values even if driver failed
-        * to read FCoE param config regions
-        */
-       if (lpfc_sli4_read_fcoe_params(phba, mboxq))
-               lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_INIT,
-                       "2570 Failed to read FCoE parameters\n");
-
        /* Issue READ_REV to collect vpd and FW information. */
        vpd_size = SLI4_PAGE_SIZE;
        vpd = kzalloc(vpd_size, GFP_KERNEL);
@@ -5595,6 +5948,27 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                kfree(vpd);
                goto out_free_mbox;
        }
+
+       /*
+        * Continue initialization with default values even if driver failed
+        * to read FCoE param config regions, only read parameters if the
+        * board is FCoE
+        */
+       if (phba->hba_flag & HBA_FCOE_MODE &&
+           lpfc_sli4_read_fcoe_params(phba))
+               lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_INIT,
+                       "2570 Failed to read FCoE parameters\n");
+
+       /*
+        * Retrieve sli4 device physical port name, failure of doing it
+        * is considered as non-fatal.
+        */
+       rc = lpfc_sli4_retrieve_pport_name(phba);
+       if (!rc)
+               lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+                               "3080 Successful retrieving SLI4 device "
+                               "physical port name: %s.\n", phba->Port);
+
        /*
         * Evaluate the read rev and vpd data. Populate the driver
         * state with the results. If this routine fails, the failure
@@ -5665,9 +6039,13 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
         * then turn off the global config parameters to disable the
         * feature in the driver.  This is not a fatal error.
         */
-       if ((phba->cfg_enable_bg) &&
-           !(bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs)))
-               ftr_rsp++;
+       phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED;
+       if (phba->cfg_enable_bg) {
+               if (bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))
+                       phba->sli3_options |= LPFC_SLI3_BG_ENABLED;
+               else
+                       ftr_rsp++;
+       }
 
        if (phba->max_vpi && phba->cfg_enable_npiv &&
            !(bf_get(lpfc_mbx_rq_ftr_rsp_npiv, &mqe->un.req_ftrs)))
@@ -5701,6 +6079,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                                "rc = x%x\n", rc);
                goto out_free_mbox;
        }
+       /* update physical xri mappings in the scsi buffers */
+       lpfc_scsi_buf_update(phba);
 
        /* Read the port's service parameters. */
        rc = lpfc_read_sparam(phba, mboxq, vport->vpi);
@@ -5784,12 +6164,20 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                goto out_free_mbox;
        }
 
+       /* Create all the SLI4 queues */
+       rc = lpfc_sli4_queue_create(phba);
+       if (rc) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3089 Failed to allocate queues\n");
+               rc = -ENODEV;
+               goto out_stop_timers;
+       }
        /* Set up all the queues to the device */
        rc = lpfc_sli4_queue_setup(phba);
        if (unlikely(rc)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
                                "0381 Error %d during queue setup.\n ", rc);
-               goto out_stop_timers;
+               goto out_destroy_queue;
        }
 
        /* Arm the CQs and then EQs on device */
@@ -5854,7 +6242,11 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                rc = 0;
                phba->fcf.fcfi = bf_get(lpfc_reg_fcfi_fcfi,
                                        &mboxq->u.mqe.un.reg_fcfi);
+
+               /* Check if the port is configured to be disabled */
+               lpfc_sli_read_link_ste(phba);
        }
+
        /*
         * The port is ready, set the host's link state to LINK_DOWN
         * in preparation for link interrupts.
@@ -5862,15 +6254,35 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
        spin_lock_irq(&phba->hbalock);
        phba->link_state = LPFC_LINK_DOWN;
        spin_unlock_irq(&phba->hbalock);
-       if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK)
-               rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+       if (!(phba->hba_flag & HBA_FCOE_MODE) &&
+           (phba->hba_flag & LINK_DISABLED)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI,
+                               "3103 Adapter Link is disabled.\n");
+               lpfc_down_link(phba, mboxq);
+               rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+               if (rc != MBX_SUCCESS) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI,
+                                       "3104 Adapter failed to issue "
+                                       "DOWN_LINK mbox cmd, rc:x%x\n", rc);
+                       goto out_unset_queue;
+               }
+       } else if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) {
+               /* don't perform init_link on SLI4 FC port loopback test */
+               if (!(phba->link_flag & LS_LOOPBACK_MODE)) {
+                       rc = phba->lpfc_hba_init_link(phba);
+                       if (rc)
+                               goto out_unset_queue;
+               }
+       }
+       mempool_free(mboxq, phba->mbox_mem_pool);
+       return rc;
 out_unset_queue:
        /* Unset all the queues set up in this routine when error out */
-       if (rc)
-               lpfc_sli4_queue_unset(phba);
+       lpfc_sli4_queue_unset(phba);
+out_destroy_queue:
+       lpfc_sli4_queue_destroy(phba);
 out_stop_timers:
-       if (rc)
-               lpfc_stop_hba_timers(phba);
+       lpfc_stop_hba_timers(phba);
 out_free_mbox:
        mempool_free(mboxq, phba->mbox_mem_pool);
        return rc;
@@ -6165,7 +6577,7 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
                }
                /* timeout active mbox command */
                mod_timer(&psli->mbox_tmo, (jiffies +
-                              (HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand))));
+                              (HZ * lpfc_mbox_tmo_val(phba, pmbox))));
        }
 
        /* Mailbox cmd <cmd> issue */
@@ -6289,9 +6701,8 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
                                                       drvr_flag);
                        goto out_not_finished;
                }
-               timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
-                                                            mb->mbxCommand) *
-                                          1000) + jiffies;
+               timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, pmbox) *
+                                                       1000) + jiffies;
                i = 0;
                /* Wait for command to complete */
                while (((word0 & OWN_CHIP) == OWN_CHIP) ||
@@ -6402,21 +6813,21 @@ static int
 lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
 {
        struct lpfc_sli *psli = &phba->sli;
-       uint8_t actcmd = MBX_HEARTBEAT;
        int rc = 0;
-       unsigned long timeout;
+       unsigned long timeout = 0;
 
        /* Mark the asynchronous mailbox command posting as blocked */
        spin_lock_irq(&phba->hbalock);
        psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
-       if (phba->sli.mbox_active)
-               actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
-       spin_unlock_irq(&phba->hbalock);
        /* Determine how long we might wait for the active mailbox
         * command to be gracefully completed by firmware.
         */
-       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) * 1000) +
-                                  jiffies;
+       if (phba->sli.mbox_active)
+               timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+                                               phba->sli.mbox_active) *
+                                               1000) + jiffies;
+       spin_unlock_irq(&phba->hbalock);
+
        /* Wait for the outstnading mailbox command to complete */
        while (phba->sli.mbox_active) {
                /* Check active mailbox complete status every 2ms */
@@ -6511,11 +6922,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
                spin_unlock_irqrestore(&phba->hbalock, iflag);
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                               "(%d):2532 Mailbox command x%x (x%x) "
+                               "(%d):2532 Mailbox command x%x (x%x/x%x) "
                                "cannot issue Data: x%x x%x\n",
                                mboxq->vport ? mboxq->vport->vpi : 0,
                                mboxq->u.mb.mbxCommand,
-                               lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                               lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                               lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                                psli->sli_flag, MBX_POLL);
                return MBXERR_ERROR;
        }
@@ -6538,7 +6950,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        dma_address = &phba->sli4_hba.bmbx.dma_address;
        writel(dma_address->addr_hi, phba->sli4_hba.BMBXregaddr);
 
-       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd)
+       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
                                   * 1000) + jiffies;
        do {
                bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
@@ -6554,7 +6966,7 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 
        /* Post the low mailbox dma address to the port. */
        writel(dma_address->addr_lo, phba->sli4_hba.BMBXregaddr);
-       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mbx_cmnd)
+       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, mboxq)
                                   * 1000) + jiffies;
        do {
                bmbx_reg.word0 = readl(phba->sli4_hba.BMBXregaddr);
@@ -6593,11 +7005,12 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                lpfc_sli4_swap_str(phba, mboxq);
 
        lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
-                       "(%d):0356 Mailbox cmd x%x (x%x) Status x%x "
+                       "(%d):0356 Mailbox cmd x%x (x%x/x%x) Status x%x "
                        "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x x%x x%x"
                        " x%x x%x CQ: x%x x%x x%x x%x\n",
-                       mboxq->vport ? mboxq->vport->vpi : 0,
-                       mbx_cmnd, lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                       mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd,
+                       lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                       lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                        bf_get(lpfc_mqe_status, mb),
                        mb->un.mb_words[0], mb->un.mb_words[1],
                        mb->un.mb_words[2], mb->un.mb_words[3],
@@ -6637,14 +7050,18 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
        unsigned long iflags;
        int rc;
 
+       /* dump from issue mailbox command if setup */
+       lpfc_idiag_mbxacc_dump_issue_mbox(phba, &mboxq->u.mb);
+
        rc = lpfc_mbox_dev_check(phba);
        if (unlikely(rc)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                               "(%d):2544 Mailbox command x%x (x%x) "
+                               "(%d):2544 Mailbox command x%x (x%x/x%x) "
                                "cannot issue Data: x%x x%x\n",
                                mboxq->vport ? mboxq->vport->vpi : 0,
                                mboxq->u.mb.mbxCommand,
-                               lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                               lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                               lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                                psli->sli_flag, flag);
                goto out_not_finished;
        }
@@ -6658,20 +7075,25 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
                if (rc != MBX_SUCCESS)
                        lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
                                        "(%d):2541 Mailbox command x%x "
-                                       "(x%x) cannot issue Data: x%x x%x\n",
+                                       "(x%x/x%x) cannot issue Data: "
+                                       "x%x x%x\n",
                                        mboxq->vport ? mboxq->vport->vpi : 0,
                                        mboxq->u.mb.mbxCommand,
-                                       lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                                       lpfc_sli_config_mbox_subsys_get(phba,
+                                                                       mboxq),
+                                       lpfc_sli_config_mbox_opcode_get(phba,
+                                                                       mboxq),
                                        psli->sli_flag, flag);
                return rc;
        } else if (flag == MBX_POLL) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
                                "(%d):2542 Try to issue mailbox command "
-                               "x%x (x%x) synchronously ahead of async"
+                               "x%x (x%x/x%x) synchronously ahead of async"
                                "mailbox command queue: x%x x%x\n",
                                mboxq->vport ? mboxq->vport->vpi : 0,
                                mboxq->u.mb.mbxCommand,
-                               lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                               lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                               lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                                psli->sli_flag, flag);
                /* Try to block the asynchronous mailbox posting */
                rc = lpfc_sli4_async_mbox_block(phba);
@@ -6680,16 +7102,18 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
                        rc = lpfc_sli4_post_sync_mbox(phba, mboxq);
                        if (rc != MBX_SUCCESS)
                                lpfc_printf_log(phba, KERN_ERR,
-                                               LOG_MBOX | LOG_SLI,
-                                               "(%d):2597 Mailbox command "
-                                               "x%x (x%x) cannot issue "
-                                               "Data: x%x x%x\n",
-                                               mboxq->vport ?
-                                               mboxq->vport->vpi : 0,
-                                               mboxq->u.mb.mbxCommand,
-                                               lpfc_sli4_mbox_opcode_get(phba,
-                                                               mboxq),
-                                               psli->sli_flag, flag);
+                                       LOG_MBOX | LOG_SLI,
+                                       "(%d):2597 Mailbox command "
+                                       "x%x (x%x/x%x) cannot issue "
+                                       "Data: x%x x%x\n",
+                                       mboxq->vport ?
+                                       mboxq->vport->vpi : 0,
+                                       mboxq->u.mb.mbxCommand,
+                                       lpfc_sli_config_mbox_subsys_get(phba,
+                                                                       mboxq),
+                                       lpfc_sli_config_mbox_opcode_get(phba,
+                                                                       mboxq),
+                                       psli->sli_flag, flag);
                        /* Unblock the async mailbox posting afterward */
                        lpfc_sli4_async_mbox_unblock(phba);
                }
@@ -6700,11 +7124,12 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
        rc = lpfc_mbox_cmd_check(phba, mboxq);
        if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                               "(%d):2543 Mailbox command x%x (x%x) "
+                               "(%d):2543 Mailbox command x%x (x%x/x%x) "
                                "cannot issue Data: x%x x%x\n",
                                mboxq->vport ? mboxq->vport->vpi : 0,
                                mboxq->u.mb.mbxCommand,
-                               lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                               lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                               lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                                psli->sli_flag, flag);
                goto out_not_finished;
        }
@@ -6716,10 +7141,11 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
        spin_unlock_irqrestore(&phba->hbalock, iflags);
        lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
                        "(%d):0354 Mbox cmd issue - Enqueue Data: "
-                       "x%x (x%x) x%x x%x x%x\n",
+                       "x%x (x%x/x%x) x%x x%x x%x\n",
                        mboxq->vport ? mboxq->vport->vpi : 0xffffff,
                        bf_get(lpfc_mqe_command, &mboxq->u.mqe),
-                       lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                       lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                       lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                        phba->pport->port_state,
                        psli->sli_flag, MBX_NOWAIT);
        /* Wake up worker thread to transport mailbox command from head */
@@ -6796,13 +7222,14 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
 
        /* Start timer for the mbox_tmo and log some mailbox post messages */
        mod_timer(&psli->mbox_tmo, (jiffies +
-                 (HZ * lpfc_mbox_tmo_val(phba, mbx_cmnd))));
+                 (HZ * lpfc_mbox_tmo_val(phba, mboxq))));
 
        lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
-                       "(%d):0355 Mailbox cmd x%x (x%x) issue Data: "
+                       "(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: "
                        "x%x x%x\n",
                        mboxq->vport ? mboxq->vport->vpi : 0, mbx_cmnd,
-                       lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                       lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                       lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                        phba->pport->port_state, psli->sli_flag);
 
        if (mbx_cmnd != MBX_HEARTBEAT) {
@@ -6826,11 +7253,12 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
        rc = lpfc_sli4_mq_put(phba->sli4_hba.mbx_wq, mqe);
        if (rc != MBX_SUCCESS) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                               "(%d):2533 Mailbox command x%x (x%x) "
+                               "(%d):2533 Mailbox command x%x (x%x/x%x) "
                                "cannot issue Data: x%x x%x\n",
                                mboxq->vport ? mboxq->vport->vpi : 0,
                                mboxq->u.mb.mbxCommand,
-                               lpfc_sli4_mbox_opcode_get(phba, mboxq),
+                               lpfc_sli_config_mbox_subsys_get(phba, mboxq),
+                               lpfc_sli_config_mbox_opcode_get(phba, mboxq),
                                psli->sli_flag, MBX_NOWAIT);
                goto out_not_finished;
        }
@@ -7115,6 +7543,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
        struct ulp_bde64 *bpl = NULL;
        struct ulp_bde64 bde;
        struct sli4_sge *sgl  = NULL;
+       struct lpfc_dmabuf *dmabuf;
        IOCB_t *icmd;
        int numBdes = 0;
        int i = 0;
@@ -7133,9 +7562,12 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
                 * have not been byteswapped yet so there is no
                 * need to swap them back.
                 */
-               bpl  = (struct ulp_bde64 *)
-                       ((struct lpfc_dmabuf *)piocbq->context3)->virt;
+               if (piocbq->context3)
+                       dmabuf = (struct lpfc_dmabuf *)piocbq->context3;
+               else
+                       return xritag;
 
+               bpl  = (struct ulp_bde64 *)dmabuf->virt;
                if (!bpl)
                        return xritag;
 
@@ -7166,6 +7598,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
                                if (inbound == 1)
                                        offset = 0;
                                bf_set(lpfc_sli4_sge_offset, sgl, offset);
+                               bf_set(lpfc_sli4_sge_type, sgl,
+                                       LPFC_SGE_TYPE_DATA);
                                offset += bde.tus.f.bdeSize;
                        }
                        sgl->word2 = cpu_to_le32(sgl->word2);
@@ -7242,6 +7676,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
        int numBdes, i;
        struct ulp_bde64 bde;
        struct lpfc_nodelist *ndlp;
+       uint32_t *pcmd;
+       uint32_t if_type;
 
        fip = phba->hba_flag & HBA_FIP_SUPPORT;
        /* The fcp commands will set command type */
@@ -7295,6 +7731,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                                iocbq->iocb.ulpCommand);
                        return IOCB_ERROR;
                }
+
                wqe->els_req.payload_len = xmit_len;
                /* Els_reguest64 has a TMO */
                bf_set(wqe_tmo, &wqe->els_req.wqe_com,
@@ -7309,9 +7746,28 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_ct, &wqe->els_req.wqe_com, ct);
                bf_set(wqe_pu, &wqe->els_req.wqe_com, 0);
                /* CCP CCPE PV PRI in word10 were set in the memcpy */
-               if (command_type == ELS_COMMAND_FIP) {
+               if (command_type == ELS_COMMAND_FIP)
                        els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK)
                                        >> LPFC_FIP_ELS_ID_SHIFT);
+               pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
+                                       iocbq->context2)->virt);
+               if_type = bf_get(lpfc_sli_intf_if_type,
+                                       &phba->sli4_hba.sli_intf);
+               if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+                       if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
+                               *pcmd == ELS_CMD_SCR ||
+                               *pcmd == ELS_CMD_PLOGI)) {
+                               bf_set(els_req64_sp, &wqe->els_req, 1);
+                               bf_set(els_req64_sid, &wqe->els_req,
+                                       iocbq->vport->fc_myDID);
+                               bf_set(wqe_ct, &wqe->els_req.wqe_com, 1);
+                               bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
+                                       phba->vpi_ids[phba->pport->vpi]);
+                       } else if (iocbq->context1) {
+                               bf_set(wqe_ct, &wqe->els_req.wqe_com, 0);
+                               bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
+                                       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
+                       }
                }
                bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com,
                       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
@@ -7330,6 +7786,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                /* The entire sequence is transmitted for this IOCB */
                xmit_len = total_len;
                cmnd = CMD_XMIT_SEQUENCE64_CR;
+               if (phba->link_flag & LS_LOOPBACK_MODE)
+                       bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1);
        case CMD_XMIT_SEQUENCE64_CR:
                /* word3 iocb=io_tag32 wqe=reserved */
                wqe->xmit_sequence.rsvd3 = 0;
@@ -7472,6 +7930,16 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0);
                bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp,
                       phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
+               pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
+                                       iocbq->context2)->virt);
+               if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
+                               bf_set(els_req64_sp, &wqe->els_req, 1);
+                               bf_set(els_req64_sid, &wqe->els_req,
+                                       iocbq->vport->fc_myDID);
+                               bf_set(wqe_ct, &wqe->els_req.wqe_com, 1);
+                               bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
+                                       phba->vpi_ids[phba->pport->vpi]);
+               }
                command_type = OTHER_COMMAND;
                break;
        case CMD_CLOSE_XRI_CN:
@@ -7663,6 +8131,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
                 */
                if (piocb->iocb_flag & LPFC_IO_FCP)
                        piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba);
+               if (unlikely(!phba->sli4_hba.fcp_wq))
+                       return IOCB_ERROR;
                if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx],
                                     &wqe))
                        return IOCB_ERROR;
@@ -7799,6 +8269,137 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
        return 0;
 }
 
+/* lpfc_sli_abts_recover_port - Recover a port that failed an ABTS.
+ * @vport: pointer to virtual port object.
+ * @ndlp: nodelist pointer for the impacted rport.
+ *
+ * The driver calls this routine in response to a XRI ABORT CQE
+ * event from the port.  In this event, the driver is required to
+ * recover its login to the rport even though its login may be valid
+ * from the driver's perspective.  The failed ABTS notice from the
+ * port indicates the rport is not responding.
+ */
+static void
+lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
+                          struct lpfc_nodelist *ndlp)
+{
+       struct Scsi_Host *shost;
+       struct lpfc_hba *phba;
+       unsigned long flags = 0;
+
+       shost = lpfc_shost_from_vport(vport);
+       phba = vport->phba;
+       if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) {
+               lpfc_printf_log(phba, KERN_INFO,
+                       LOG_SLI, "3093 No rport recovery needed. "
+                       "rport in state 0x%x\n",
+                       ndlp->nlp_state);
+               return;
+       }
+       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                       "3094 Start rport recovery on shost id 0x%x "
+                       "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x "
+                       "flags 0x%x\n",
+                       shost->host_no, ndlp->nlp_DID,
+                       vport->vpi, ndlp->nlp_rpi, ndlp->nlp_state,
+                       ndlp->nlp_flag);
+       /*
+        * The rport is not responding.  Don't attempt ADISC recovery.
+        * Remove the FCP-2 flag to force a PLOGI.
+        */
+       spin_lock_irqsave(shost->host_lock, flags);
+       ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
+       spin_unlock_irqrestore(shost->host_lock, flags);
+       lpfc_disc_state_machine(vport, ndlp, NULL,
+                               NLP_EVT_DEVICE_RECOVERY);
+       lpfc_cancel_retry_delay_tmo(vport, ndlp);
+       spin_lock_irqsave(shost->host_lock, flags);
+       ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+       spin_unlock_irqrestore(shost->host_lock, flags);
+       lpfc_disc_start(vport);
+}
+
+/* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port.
+ * @phba: Pointer to HBA context object.
+ * @iocbq: Pointer to iocb object.
+ *
+ * The async_event handler calls this routine when it receives
+ * an ASYNC_STATUS_CN event from the port.  The port generates
+ * this event when an Abort Sequence request to an rport fails
+ * twice in succession.  The abort could be originated by the
+ * driver or by the port.  The ABTS could have been for an ELS
+ * or FCP IO.  The port only generates this event when an ABTS
+ * fails to complete after one retry.
+ */
+static void
+lpfc_sli_abts_err_handler(struct lpfc_hba *phba,
+                         struct lpfc_iocbq *iocbq)
+{
+       struct lpfc_nodelist *ndlp = NULL;
+       uint16_t rpi = 0, vpi = 0;
+       struct lpfc_vport *vport = NULL;
+
+       /* The rpi in the ulpContext is vport-sensitive. */
+       vpi = iocbq->iocb.un.asyncstat.sub_ctxt_tag;
+       rpi = iocbq->iocb.ulpContext;
+
+       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                       "3092 Port generated ABTS async event "
+                       "on vpi %d rpi %d status 0x%x\n",
+                       vpi, rpi, iocbq->iocb.ulpStatus);
+
+       vport = lpfc_find_vport_by_vpid(phba, vpi);
+       if (!vport)
+               goto err_exit;
+       ndlp = lpfc_findnode_rpi(vport, rpi);
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+               goto err_exit;
+
+       if (iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
+               lpfc_sli_abts_recover_port(vport, ndlp);
+       return;
+
+ err_exit:
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "3095 Event Context not found, no "
+                       "action on vpi %d rpi %d status 0x%x, reason 0x%x\n",
+                       iocbq->iocb.ulpContext, iocbq->iocb.ulpStatus,
+                       vpi, rpi);
+}
+
+/* lpfc_sli4_abts_err_handler - handle a failed ABTS request from an SLI4 port.
+ * @phba: pointer to HBA context object.
+ * @ndlp: nodelist pointer for the impacted rport.
+ * @axri: pointer to the wcqe containing the failed exchange.
+ *
+ * The driver calls this routine when it receives an ABORT_XRI_FCP CQE from the
+ * port.  The port generates this event when an abort exchange request to an
+ * rport fails twice in succession with no reply.  The abort could be originated
+ * by the driver or by the port.  The ABTS could have been for an ELS or FCP IO.
+ */
+void
+lpfc_sli4_abts_err_handler(struct lpfc_hba *phba,
+                          struct lpfc_nodelist *ndlp,
+                          struct sli4_wcqe_xri_aborted *axri)
+{
+       struct lpfc_vport *vport;
+
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                               "3115 Node Context not found, driver "
+                               "ignoring abts err event\n");
+       vport = ndlp->vport;
+       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                       "3116 Port generated FCP XRI ABORT event on "
+                       "vpi %d rpi %d xri x%x status 0x%x\n",
+                       ndlp->vport->vpi, ndlp->nlp_rpi,
+                       bf_get(lpfc_wcqe_xa_xri, axri),
+                       bf_get(lpfc_wcqe_xa_status, axri));
+
+       if (bf_get(lpfc_wcqe_xa_status, axri) == IOSTAT_LOCAL_REJECT)
+               lpfc_sli_abts_recover_port(vport, ndlp);
+}
+
 /**
  * lpfc_sli_async_event_handler - ASYNC iocb handler function
  * @phba: Pointer to HBA context object.
@@ -7818,63 +8419,58 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
 {
        IOCB_t *icmd;
        uint16_t evt_code;
-       uint16_t temp;
        struct temp_event temp_event_data;
        struct Scsi_Host *shost;
        uint32_t *iocb_w;
 
        icmd = &iocbq->iocb;
        evt_code = icmd->un.asyncstat.evt_code;
-       temp = icmd->ulpContext;
 
-       if ((evt_code != ASYNC_TEMP_WARN) &&
-               (evt_code != ASYNC_TEMP_SAFE)) {
+       switch (evt_code) {
+       case ASYNC_TEMP_WARN:
+       case ASYNC_TEMP_SAFE:
+               temp_event_data.data = (uint32_t) icmd->ulpContext;
+               temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
+               if (evt_code == ASYNC_TEMP_WARN) {
+                       temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
+                       lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
+                               "0347 Adapter is very hot, please take "
+                               "corrective action. temperature : %d Celsius\n",
+                               (uint32_t) icmd->ulpContext);
+               } else {
+                       temp_event_data.event_code = LPFC_NORMAL_TEMP;
+                       lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
+                               "0340 Adapter temperature is OK now. "
+                               "temperature : %d Celsius\n",
+                               (uint32_t) icmd->ulpContext);
+               }
+
+               /* Send temperature change event to applications */
+               shost = lpfc_shost_from_vport(phba->pport);
+               fc_host_post_vendor_event(shost, fc_get_event_number(),
+                       sizeof(temp_event_data), (char *) &temp_event_data,
+                       LPFC_NL_VENDOR_ID);
+               break;
+       case ASYNC_STATUS_CN:
+               lpfc_sli_abts_err_handler(phba, iocbq);
+               break;
+       default:
                iocb_w = (uint32_t *) icmd;
-               lpfc_printf_log(phba,
-                       KERN_ERR,
-                       LOG_SLI,
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                        "0346 Ring %d handler: unexpected ASYNC_STATUS"
                        " evt_code 0x%x\n"
                        "W0  0x%08x W1  0x%08x W2  0x%08x W3  0x%08x\n"
                        "W4  0x%08x W5  0x%08x W6  0x%08x W7  0x%08x\n"
                        "W8  0x%08x W9  0x%08x W10 0x%08x W11 0x%08x\n"
                        "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n",
-                       pring->ringno,
-                       icmd->un.asyncstat.evt_code,
+                       pring->ringno, icmd->un.asyncstat.evt_code,
                        iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3],
                        iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7],
                        iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11],
                        iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]);
 
-               return;
-       }
-       temp_event_data.data = (uint32_t)temp;
-       temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
-       if (evt_code == ASYNC_TEMP_WARN) {
-               temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
-               lpfc_printf_log(phba,
-                               KERN_ERR,
-                               LOG_TEMP,
-                               "0347 Adapter is very hot, please take "
-                               "corrective action. temperature : %d Celsius\n",
-                               temp);
-       }
-       if (evt_code == ASYNC_TEMP_SAFE) {
-               temp_event_data.event_code = LPFC_NORMAL_TEMP;
-               lpfc_printf_log(phba,
-                               KERN_ERR,
-                               LOG_TEMP,
-                               "0340 Adapter temperature is OK now. "
-                               "temperature : %d Celsius\n",
-                               temp);
+               break;
        }
-
-       /* Send temperature change event to applications */
-       shost = lpfc_shost_from_vport(phba->pport);
-       fc_host_post_vendor_event(shost, fc_get_event_number(),
-               sizeof(temp_event_data), (char *) &temp_event_data,
-               LPFC_NL_VENDOR_ID);
-
 }
 
 
@@ -8449,12 +9045,14 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 {
        IOCB_t *irsp = &rspiocb->iocb;
        uint16_t abort_iotag, abort_context;
-       struct lpfc_iocbq *abort_iocb;
-       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
-
-       abort_iocb = NULL;
+       struct lpfc_iocbq *abort_iocb = NULL;
 
        if (irsp->ulpStatus) {
+
+               /*
+                * Assume that the port already completed and returned, or
+                * will return the iocb. Just Log the message.
+                */
                abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
                abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
 
@@ -8472,68 +9070,15 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                         */
                        abort_iocb = phba->sli.iocbq_lookup[abort_context];
 
-               /*
-                *  If the iocb is not found in Firmware queue the iocb
-                *  might have completed already. Do not free it again.
-                */
-               if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
-                       if (irsp->un.ulpWord[4] != IOERR_NO_XRI) {
-                               spin_unlock_irq(&phba->hbalock);
-                               lpfc_sli_release_iocbq(phba, cmdiocb);
-                               return;
-                       }
-                       /* For SLI4 the ulpContext field for abort IOCB
-                        * holds the iotag of the IOCB being aborted so
-                        * the local abort_context needs to be reset to
-                        * match the aborted IOCBs ulpContext.
-                        */
-                       if (abort_iocb && phba->sli_rev == LPFC_SLI_REV4)
-                               abort_context = abort_iocb->iocb.ulpContext;
-               }
-
                lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_SLI,
                                "0327 Cannot abort els iocb %p "
                                "with tag %x context %x, abort status %x, "
                                "abort code %x\n",
                                abort_iocb, abort_iotag, abort_context,
                                irsp->ulpStatus, irsp->un.ulpWord[4]);
-               /*
-                * make sure we have the right iocbq before taking it
-                * off the txcmplq and try to call completion routine.
-                */
-               if (!abort_iocb ||
-                   abort_iocb->iocb.ulpContext != abort_context ||
-                   (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0)
-                       spin_unlock_irq(&phba->hbalock);
-               else if (phba->sli_rev < LPFC_SLI_REV4) {
-                       /*
-                        * leave the SLI4 aborted command on the txcmplq
-                        * list and the command complete WCQE's XB bit
-                        * will tell whether the SGL (XRI) can be released
-                        * immediately or to the aborted SGL list for the
-                        * following abort XRI from the HBA.
-                        */
-                       list_del_init(&abort_iocb->list);
-                       if (abort_iocb->iocb_flag & LPFC_IO_ON_Q) {
-                               abort_iocb->iocb_flag &= ~LPFC_IO_ON_Q;
-                               pring->txcmplq_cnt--;
-                       }
 
-                       /* Firmware could still be in progress of DMAing
-                        * payload, so don't free data buffer till after
-                        * a hbeat.
-                        */
-                       abort_iocb->iocb_flag |= LPFC_DELAY_MEM_FREE;
-                       abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
-                       spin_unlock_irq(&phba->hbalock);
-
-                       abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
-                       abort_iocb->iocb.un.ulpWord[4] = IOERR_ABORT_REQUESTED;
-                       (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb);
-               } else
-                       spin_unlock_irq(&phba->hbalock);
+               spin_unlock_irq(&phba->hbalock);
        }
-
        lpfc_sli_release_iocbq(phba, cmdiocb);
        return;
 }
@@ -8884,6 +9429,14 @@ void
 lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        struct lpfc_iocbq *rspiocb)
 {
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "3096 ABORT_XRI_CN completing on xri x%x "
+                       "original iotag x%x, abort cmd iotag x%x "
+                       "status 0x%x, reason 0x%x\n",
+                       cmdiocb->iocb.un.acxri.abortContextTag,
+                       cmdiocb->iocb.un.acxri.abortIoTag,
+                       cmdiocb->iotag, rspiocb->iocb.ulpStatus,
+                       rspiocb->iocb.un.ulpWord[4]);
        lpfc_sli_release_iocbq(phba, cmdiocb);
        return;
 }
@@ -9203,7 +9756,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
 
        /* now issue the command */
        retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
-
        if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
                wait_event_interruptible_timeout(done_q,
                                pmboxq->mbox_flag & LPFC_MBX_WAKE,
@@ -9247,23 +9799,24 @@ void
 lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *phba)
 {
        struct lpfc_sli *psli = &phba->sli;
-       uint8_t actcmd = MBX_HEARTBEAT;
        unsigned long timeout;
 
+       timeout = msecs_to_jiffies(LPFC_MBOX_TMO * 1000) + jiffies;
        spin_lock_irq(&phba->hbalock);
        psli->sli_flag |= LPFC_SLI_ASYNC_MBX_BLK;
        spin_unlock_irq(&phba->hbalock);
 
        if (psli->sli_flag & LPFC_SLI_ACTIVE) {
                spin_lock_irq(&phba->hbalock);
-               if (phba->sli.mbox_active)
-                       actcmd = phba->sli.mbox_active->u.mb.mbxCommand;
-               spin_unlock_irq(&phba->hbalock);
                /* Determine how long we might wait for the active mailbox
                 * command to be gracefully completed by firmware.
                 */
-               timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, actcmd) *
-                                          1000) + jiffies;
+               if (phba->sli.mbox_active)
+                       timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+                                               phba->sli.mbox_active) *
+                                               1000) + jiffies;
+               spin_unlock_irq(&phba->hbalock);
+
                while (phba->sli.mbox_active) {
                        /* Check active mailbox complete status every 2ms */
                        msleep(2);
@@ -9397,7 +9950,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba)
                        phba->work_status[1] =
                                readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "2885 Port Error Detected: "
+                                       "2885 Port Status Event: "
                                        "port status reg 0x%x, "
                                        "port smphr reg 0x%x, "
                                        "error 1=0x%x, error 2=0x%x\n",
@@ -10259,12 +10812,17 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe)
        /* Move mbox data to caller's mailbox region, do endian swapping */
        if (pmb->mbox_cmpl && mbox)
                lpfc_sli_pcimem_bcopy(mbox, mqe, sizeof(struct lpfc_mqe));
-       /* Set the mailbox status with SLI4 range 0x4000 */
-       mcqe_status = bf_get(lpfc_mcqe_status, mcqe);
-       if (mcqe_status != MB_CQE_STATUS_SUCCESS)
-               bf_set(lpfc_mqe_status, mqe,
-                      (LPFC_MBX_ERROR_RANGE | mcqe_status));
 
+       /*
+        * For mcqe errors, conditionally move a modified error code to
+        * the mbox so that the error will not be missed.
+        */
+       mcqe_status = bf_get(lpfc_mcqe_status, mcqe);
+       if (mcqe_status != MB_CQE_STATUS_SUCCESS) {
+               if (bf_get(lpfc_mqe_status, mqe) == MBX_SUCCESS)
+                       bf_set(lpfc_mqe_status, mqe,
+                              (LPFC_MBX_ERROR_RANGE | mcqe_status));
+       }
        if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
                pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_MBOX_VPORT,
@@ -10398,6 +10956,9 @@ static void
 lpfc_sli4_sp_handle_rel_wcqe(struct lpfc_hba *phba,
                             struct lpfc_wcqe_release *wcqe)
 {
+       /* sanity check on queue memory */
+       if (unlikely(!phba->sli4_hba.els_wq))
+               return;
        /* Check for the slow-path ELS work queue */
        if (bf_get(lpfc_wcqe_r_wq_id, wcqe) == phba->sli4_hba.els_wq->queue_id)
                lpfc_sli4_wq_release(phba->sli4_hba.els_wq,
@@ -10487,6 +11048,10 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
        uint32_t status, rq_id;
        unsigned long iflags;
 
+       /* sanity check on queue memory */
+       if (unlikely(!hrq) || unlikely(!drq))
+               return workposted;
+
        if (bf_get(lpfc_cqe_code, rcqe) == CQE_CODE_RECEIVE_V1)
                rq_id = bf_get(lpfc_rcqe_rq_id_v1, rcqe);
        else
@@ -10621,6 +11186,9 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
 
        /* Search for completion queue pointer matching this cqid */
        speq = phba->sli4_hba.sp_eq;
+       /* sanity check on queue memory */
+       if (unlikely(!speq))
+               return;
        list_for_each_entry(childq, &speq->child_list, list) {
                if (childq->queue_id == cqid) {
                        cq = childq;
@@ -10640,7 +11208,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
        case LPFC_MCQ:
                while ((cqe = lpfc_sli4_cq_get(cq))) {
                        workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe);
-                       if (!(++ecount % LPFC_GET_QE_REL_INT))
+                       if (!(++ecount % cq->entry_repost))
                                lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
                }
                break;
@@ -10652,7 +11220,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
                        else
                                workposted |= lpfc_sli4_sp_handle_cqe(phba, cq,
                                                                      cqe);
-                       if (!(++ecount % LPFC_GET_QE_REL_INT))
+                       if (!(++ecount % cq->entry_repost))
                                lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
                }
                break;
@@ -10862,12 +11430,18 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
                return;
        }
 
+       if (unlikely(!phba->sli4_hba.fcp_cq)) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                               "3146 Fast-path completion queues "
+                               "does not exist\n");
+               return;
+       }
        cq = phba->sli4_hba.fcp_cq[fcp_cqidx];
        if (unlikely(!cq)) {
                if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
                        lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                        "0367 Fast-path completion queue "
-                                       "does not exist\n");
+                                       "(%d) does not exist\n", fcp_cqidx);
                return;
        }
 
@@ -10884,7 +11458,7 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
        /* Process all the entries to the CQ */
        while ((cqe = lpfc_sli4_cq_get(cq))) {
                workposted |= lpfc_sli4_fp_handle_wcqe(phba, cq, cqe);
-               if (!(++ecount % LPFC_GET_QE_REL_INT))
+               if (!(++ecount % cq->entry_repost))
                        lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
        }
 
@@ -10954,6 +11528,8 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id)
 
        /* Get to the EQ struct associated with this vector */
        speq = phba->sli4_hba.sp_eq;
+       if (unlikely(!speq))
+               return IRQ_NONE;
 
        /* Check device state for handling interrupt */
        if (unlikely(lpfc_intr_state_check(phba))) {
@@ -10971,7 +11547,7 @@ lpfc_sli4_sp_intr_handler(int irq, void *dev_id)
         */
        while ((eqe = lpfc_sli4_eq_get(speq))) {
                lpfc_sli4_sp_handle_eqe(phba, eqe);
-               if (!(++ecount % LPFC_GET_QE_REL_INT))
+               if (!(++ecount % speq->entry_repost))
                        lpfc_sli4_eq_release(speq, LPFC_QUEUE_NOARM);
        }
 
@@ -11031,9 +11607,13 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id)
 
        if (unlikely(!phba))
                return IRQ_NONE;
+       if (unlikely(!phba->sli4_hba.fp_eq))
+               return IRQ_NONE;
 
        /* Get to the EQ struct associated with this vector */
        fpeq = phba->sli4_hba.fp_eq[fcp_eqidx];
+       if (unlikely(!fpeq))
+               return IRQ_NONE;
 
        /* Check device state for handling interrupt */
        if (unlikely(lpfc_intr_state_check(phba))) {
@@ -11051,7 +11631,7 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id)
         */
        while ((eqe = lpfc_sli4_eq_get(fpeq))) {
                lpfc_sli4_fp_handle_eqe(phba, eqe, fcp_eqidx);
-               if (!(++ecount % LPFC_GET_QE_REL_INT))
+               if (!(++ecount % fpeq->entry_repost))
                        lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_NOARM);
        }
 
@@ -11203,6 +11783,15 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
        }
        queue->entry_size = entry_size;
        queue->entry_count = entry_count;
+
+       /*
+        * entry_repost is calculated based on the number of entries in the
+        * queue. This works out except for RQs. If buffers are NOT initially
+        * posted for every RQE, entry_repost should be adjusted accordingly.
+        */
+       queue->entry_repost = (entry_count >> 3);
+       if (queue->entry_repost < LPFC_QUEUE_MIN_REPOST)
+               queue->entry_repost = LPFC_QUEUE_MIN_REPOST;
        queue->phba = phba;
 
        return queue;
@@ -11243,6 +11832,9 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax)
        uint16_t dmult;
        uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
 
+       /* sanity check on queue memory */
+       if (!eq)
+               return -ENODEV;
        if (!phba->sli4_hba.pc_sli4_params.supported)
                hw_page_size = SLI4_PAGE_SIZE;
 
@@ -11359,6 +11951,9 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
        union lpfc_sli4_cfg_shdr *shdr;
        uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
 
+       /* sanity check on queue memory */
+       if (!cq || !eq)
+               return -ENODEV;
        if (!phba->sli4_hba.pc_sli4_params.supported)
                hw_page_size = SLI4_PAGE_SIZE;
 
@@ -11541,6 +12136,9 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
        union lpfc_sli4_cfg_shdr *shdr;
        uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
 
+       /* sanity check on queue memory */
+       if (!mq || !cq)
+               return -ENODEV;
        if (!phba->sli4_hba.pc_sli4_params.supported)
                hw_page_size = SLI4_PAGE_SIZE;
 
@@ -11691,6 +12289,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
        uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
        struct dma_address *page;
 
+       /* sanity check on queue memory */
+       if (!wq || !cq)
+               return -ENODEV;
        if (!phba->sli4_hba.pc_sli4_params.supported)
                hw_page_size = SLI4_PAGE_SIZE;
 
@@ -11759,6 +12360,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
        wq->subtype = subtype;
        wq->host_index = 0;
        wq->hba_index = 0;
+       wq->entry_repost = LPFC_RELEASE_NOTIFICATION_INTERVAL;
 
        /* link the wq onto the parent cq child list */
        list_add_tail(&wq->list, &cq->child_list);
@@ -11767,6 +12369,34 @@ out:
        return status;
 }
 
+/**
+ * lpfc_rq_adjust_repost - Adjust entry_repost for an RQ
+ * @phba: HBA structure that indicates port to create a queue on.
+ * @rq:   The queue structure to use for the receive queue.
+ * @qno:  The associated HBQ number
+ *
+ *
+ * For SLI4 we need to adjust the RQ repost value based on
+ * the number of buffers that are initially posted to the RQ.
+ */
+void
+lpfc_rq_adjust_repost(struct lpfc_hba *phba, struct lpfc_queue *rq, int qno)
+{
+       uint32_t cnt;
+
+       /* sanity check on queue memory */
+       if (!rq)
+               return;
+       cnt = lpfc_hbq_defs[qno]->entry_count;
+
+       /* Recalc repost for RQs based on buffers initially posted */
+       cnt = (cnt >> 3);
+       if (cnt < LPFC_QUEUE_MIN_REPOST)
+               cnt = LPFC_QUEUE_MIN_REPOST;
+
+       rq->entry_repost = cnt;
+}
+
 /**
  * lpfc_rq_create - Create a Receive Queue on the HBA
  * @phba: HBA structure that indicates port to create a queue on.
@@ -11802,6 +12432,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
        union lpfc_sli4_cfg_shdr *shdr;
        uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
 
+       /* sanity check on queue memory */
+       if (!hrq || !drq || !cq)
+               return -ENODEV;
        if (!phba->sli4_hba.pc_sli4_params.supported)
                hw_page_size = SLI4_PAGE_SIZE;
 
@@ -12003,6 +12636,7 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq)
        uint32_t shdr_status, shdr_add_status;
        union lpfc_sli4_cfg_shdr *shdr;
 
+       /* sanity check on queue memory */
        if (!eq)
                return -ENODEV;
        mbox = mempool_alloc(eq->phba->mbox_mem_pool, GFP_KERNEL);
@@ -12058,6 +12692,7 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq)
        uint32_t shdr_status, shdr_add_status;
        union lpfc_sli4_cfg_shdr *shdr;
 
+       /* sanity check on queue memory */
        if (!cq)
                return -ENODEV;
        mbox = mempool_alloc(cq->phba->mbox_mem_pool, GFP_KERNEL);
@@ -12111,6 +12746,7 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq)
        uint32_t shdr_status, shdr_add_status;
        union lpfc_sli4_cfg_shdr *shdr;
 
+       /* sanity check on queue memory */
        if (!mq)
                return -ENODEV;
        mbox = mempool_alloc(mq->phba->mbox_mem_pool, GFP_KERNEL);
@@ -12164,6 +12800,7 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq)
        uint32_t shdr_status, shdr_add_status;
        union lpfc_sli4_cfg_shdr *shdr;
 
+       /* sanity check on queue memory */
        if (!wq)
                return -ENODEV;
        mbox = mempool_alloc(wq->phba->mbox_mem_pool, GFP_KERNEL);
@@ -12217,6 +12854,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
        uint32_t shdr_status, shdr_add_status;
        union lpfc_sli4_cfg_shdr *shdr;
 
+       /* sanity check on queue memory */
        if (!hrq || !drq)
                return -ENODEV;
        mbox = mempool_alloc(hrq->phba->mbox_mem_pool, GFP_KERNEL);
@@ -12333,7 +12971,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
        }
        /* The IOCTL status is embedded in the mailbox subheader. */
@@ -12548,7 +13186,7 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
        }
        shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12711,7 +13349,7 @@ lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba)
                if (!phba->sli4_hba.intr_enable)
                        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
                else {
-                       mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+                       mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                        rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
                }
                shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12835,7 +13473,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
        }
        shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -12991,7 +13629,7 @@ lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist,
                if (!phba->sli4_hba.intr_enable)
                        rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
                else {
-                       mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+                       mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                        rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
                }
                shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
@@ -13140,7 +13778,8 @@ lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr,
        uint32_t did = (fc_hdr->fh_d_id[0] << 16 |
                        fc_hdr->fh_d_id[1] << 8 |
                        fc_hdr->fh_d_id[2]);
-
+       if (did == Fabric_DID)
+               return phba->pport;
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
                for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
@@ -14156,7 +14795,7 @@ lpfc_sli4_init_vpi(struct lpfc_vport *vport)
        if (!mboxq)
                return -ENOMEM;
        lpfc_init_vpi(phba, mboxq, vport->vpi);
-       mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI);
+       mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
        rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
        if (rc != MBX_SUCCESS) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
@@ -14478,6 +15117,92 @@ fail_fcf_read:
        return error;
 }
 
+/**
+ * lpfc_check_next_fcf_pri
+ * phba pointer to the lpfc_hba struct for this port.
+ * This routine is called from the lpfc_sli4_fcf_rr_next_index_get
+ * routine when the rr_bmask is empty. The FCF indecies are put into the
+ * rr_bmask based on their priority level. Starting from the highest priority
+ * to the lowest. The most likely FCF candidate will be in the highest
+ * priority group. When this routine is called it searches the fcf_pri list for
+ * next lowest priority group and repopulates the rr_bmask with only those
+ * fcf_indexes.
+ * returns:
+ * 1=success 0=failure
+ **/
+int
+lpfc_check_next_fcf_pri_level(struct lpfc_hba *phba)
+{
+       uint16_t next_fcf_pri;
+       uint16_t last_index;
+       struct lpfc_fcf_pri *fcf_pri;
+       int rc;
+       int ret = 0;
+
+       last_index = find_first_bit(phba->fcf.fcf_rr_bmask,
+                       LPFC_SLI4_FCF_TBL_INDX_MAX);
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+                       "3060 Last IDX %d\n", last_index);
+       if (list_empty(&phba->fcf.fcf_pri_list)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+                       "3061 Last IDX %d\n", last_index);
+               return 0; /* Empty rr list */
+       }
+       next_fcf_pri = 0;
+       /*
+        * Clear the rr_bmask and set all of the bits that are at this
+        * priority.
+        */
+       memset(phba->fcf.fcf_rr_bmask, 0,
+                       sizeof(*phba->fcf.fcf_rr_bmask));
+       spin_lock_irq(&phba->hbalock);
+       list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+               if (fcf_pri->fcf_rec.flag & LPFC_FCF_FLOGI_FAILED)
+                       continue;
+               /*
+                * the 1st priority that has not FLOGI failed
+                * will be the highest.
+                */
+               if (!next_fcf_pri)
+                       next_fcf_pri = fcf_pri->fcf_rec.priority;
+               spin_unlock_irq(&phba->hbalock);
+               if (fcf_pri->fcf_rec.priority == next_fcf_pri) {
+                       rc = lpfc_sli4_fcf_rr_index_set(phba,
+                                               fcf_pri->fcf_rec.fcf_index);
+                       if (rc)
+                               return 0;
+               }
+               spin_lock_irq(&phba->hbalock);
+       }
+       /*
+        * if next_fcf_pri was not set above and the list is not empty then
+        * we have failed flogis on all of them. So reset flogi failed
+        * and start at the begining.
+        */
+       if (!next_fcf_pri && !list_empty(&phba->fcf.fcf_pri_list)) {
+               list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+                       fcf_pri->fcf_rec.flag &= ~LPFC_FCF_FLOGI_FAILED;
+                       /*
+                        * the 1st priority that has not FLOGI failed
+                        * will be the highest.
+                        */
+                       if (!next_fcf_pri)
+                               next_fcf_pri = fcf_pri->fcf_rec.priority;
+                       spin_unlock_irq(&phba->hbalock);
+                       if (fcf_pri->fcf_rec.priority == next_fcf_pri) {
+                               rc = lpfc_sli4_fcf_rr_index_set(phba,
+                                               fcf_pri->fcf_rec.fcf_index);
+                               if (rc)
+                                       return 0;
+                       }
+                       spin_lock_irq(&phba->hbalock);
+               }
+       } else
+               ret = 1;
+       spin_unlock_irq(&phba->hbalock);
+
+       return ret;
+}
 /**
  * lpfc_sli4_fcf_rr_next_index_get - Get next eligible fcf record index
  * @phba: pointer to lpfc hba data structure.
@@ -14494,6 +15219,7 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
        uint16_t next_fcf_index;
 
        /* Search start from next bit of currently registered FCF index */
+next_priority:
        next_fcf_index = (phba->fcf.current_rec.fcf_indx + 1) %
                                        LPFC_SLI4_FCF_TBL_INDX_MAX;
        next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
@@ -14501,17 +15227,46 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
                                       next_fcf_index);
 
        /* Wrap around condition on phba->fcf.fcf_rr_bmask */
-       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
+       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+               /*
+                * If we have wrapped then we need to clear the bits that
+                * have been tested so that we can detect when we should
+                * change the priority level.
+                */
                next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
                                               LPFC_SLI4_FCF_TBL_INDX_MAX, 0);
+       }
+
 
        /* Check roundrobin failover list empty condition */
-       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX ||
+               next_fcf_index == phba->fcf.current_rec.fcf_indx) {
+               /*
+                * If next fcf index is not found check if there are lower
+                * Priority level fcf's in the fcf_priority list.
+                * Set up the rr_bmask with all of the avaiable fcf bits
+                * at that level and continue the selection process.
+                */
+               if (lpfc_check_next_fcf_pri_level(phba))
+                       goto next_priority;
                lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
                                "2844 No roundrobin failover FCF available\n");
-               return LPFC_FCOE_FCF_NEXT_NONE;
+               if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
+                       return LPFC_FCOE_FCF_NEXT_NONE;
+               else {
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+                               "3063 Only FCF available idx %d, flag %x\n",
+                               next_fcf_index,
+                       phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag);
+                       return next_fcf_index;
+               }
        }
 
+       if (next_fcf_index < LPFC_SLI4_FCF_TBL_INDX_MAX &&
+               phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag &
+               LPFC_FCF_FLOGI_FAILED)
+               goto next_priority;
+
        lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
                        "2845 Get next roundrobin failover FCF (x%x)\n",
                        next_fcf_index);
@@ -14563,6 +15318,7 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index)
 void
 lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index)
 {
+       struct lpfc_fcf_pri *fcf_pri;
        if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
                lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
                                "2762 FCF (x%x) reached driver's book "
@@ -14571,6 +15327,14 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index)
                return;
        }
        /* Clear the eligible FCF record index bmask */
+       spin_lock_irq(&phba->hbalock);
+       list_for_each_entry(fcf_pri, &phba->fcf.fcf_pri_list, list) {
+               if (fcf_pri->fcf_rec.fcf_index == fcf_index) {
+                       list_del_init(&fcf_pri->list);
+                       break;
+               }
+       }
+       spin_unlock_irq(&phba->hbalock);
        clear_bit(fcf_index, phba->fcf.fcf_rr_bmask);
 
        lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
@@ -14709,45 +15473,42 @@ lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *phba)
 }
 
 /**
- * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled.
+ * lpfc_sli_get_config_region23 - Get sli3 port region 23 data.
  * @phba: pointer to lpfc hba data structure.
+ * @rgn23_data: pointer to configure region 23 data.
  *
- * This function read region 23 and parse TLV for port status to
- * decide if the user disaled the port. If the TLV indicates the
- * port is disabled, the hba_flag is set accordingly.
+ * This function gets SLI3 port configure region 23 data through memory dump
+ * mailbox command. When it successfully retrieves data, the size of the data
+ * will be returned, otherwise, 0 will be returned.
  **/
-void
-lpfc_sli_read_link_ste(struct lpfc_hba *phba)
+static uint32_t
+lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data)
 {
        LPFC_MBOXQ_t *pmb = NULL;
        MAILBOX_t *mb;
-       uint8_t *rgn23_data = NULL;
-       uint32_t offset = 0, data_size, sub_tlv_len, tlv_offset;
+       uint32_t offset = 0;
        int rc;
 
+       if (!rgn23_data)
+               return 0;
+
        pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!pmb) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                       "2600 lpfc_sli_read_serdes_param failed to"
-                       " allocate mailbox memory\n");
-               goto out;
+                               "2600 failed to allocate mailbox memory\n");
+               return 0;
        }
        mb = &pmb->u.mb;
 
-       /* Get adapter Region 23 data */
-       rgn23_data = kzalloc(DMP_RGN23_SIZE, GFP_KERNEL);
-       if (!rgn23_data)
-               goto out;
-
        do {
                lpfc_dump_mem(phba, pmb, offset, DMP_REGION_23);
                rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
 
                if (rc != MBX_SUCCESS) {
                        lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "2601 lpfc_sli_read_link_ste failed to"
-                               " read config region 23 rc 0x%x Status 0x%x\n",
-                               rc, mb->mbxStatus);
+                                       "2601 failed to read config "
+                                       "region 23, rc 0x%x Status 0x%x\n",
+                                       rc, mb->mbxStatus);
                        mb->un.varDmp.word_cnt = 0;
                }
                /*
@@ -14760,13 +15521,96 @@ lpfc_sli_read_link_ste(struct lpfc_hba *phba)
                        mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset;
 
                lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
-                       rgn23_data + offset,
-                       mb->un.varDmp.word_cnt);
+                                      rgn23_data + offset,
+                                      mb->un.varDmp.word_cnt);
                offset += mb->un.varDmp.word_cnt;
        } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE);
 
-       data_size = offset;
-       offset = 0;
+       mempool_free(pmb, phba->mbox_mem_pool);
+       return offset;
+}
+
+/**
+ * lpfc_sli4_get_config_region23 - Get sli4 port region 23 data.
+ * @phba: pointer to lpfc hba data structure.
+ * @rgn23_data: pointer to configure region 23 data.
+ *
+ * This function gets SLI4 port configure region 23 data through memory dump
+ * mailbox command. When it successfully retrieves data, the size of the data
+ * will be returned, otherwise, 0 will be returned.
+ **/
+static uint32_t
+lpfc_sli4_get_config_region23(struct lpfc_hba *phba, char *rgn23_data)
+{
+       LPFC_MBOXQ_t *mboxq = NULL;
+       struct lpfc_dmabuf *mp = NULL;
+       struct lpfc_mqe *mqe;
+       uint32_t data_length = 0;
+       int rc;
+
+       if (!rgn23_data)
+               return 0;
+
+       mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mboxq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3105 failed to allocate mailbox memory\n");
+               return 0;
+       }
+
+       if (lpfc_sli4_dump_cfg_rg23(phba, mboxq))
+               goto out;
+       mqe = &mboxq->u.mqe;
+       mp = (struct lpfc_dmabuf *) mboxq->context1;
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       if (rc)
+               goto out;
+       data_length = mqe->un.mb_words[5];
+       if (data_length == 0)
+               goto out;
+       if (data_length > DMP_RGN23_SIZE) {
+               data_length = 0;
+               goto out;
+       }
+       lpfc_sli_pcimem_bcopy((char *)mp->virt, rgn23_data, data_length);
+out:
+       mempool_free(mboxq, phba->mbox_mem_pool);
+       if (mp) {
+               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+               kfree(mp);
+       }
+       return data_length;
+}
+
+/**
+ * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This function read region 23 and parse TLV for port status to
+ * decide if the user disaled the port. If the TLV indicates the
+ * port is disabled, the hba_flag is set accordingly.
+ **/
+void
+lpfc_sli_read_link_ste(struct lpfc_hba *phba)
+{
+       uint8_t *rgn23_data = NULL;
+       uint32_t if_type, data_size, sub_tlv_len, tlv_offset;
+       uint32_t offset = 0;
+
+       /* Get adapter Region 23 data */
+       rgn23_data = kzalloc(DMP_RGN23_SIZE, GFP_KERNEL);
+       if (!rgn23_data)
+               goto out;
+
+       if (phba->sli_rev < LPFC_SLI_REV4)
+               data_size = lpfc_sli_get_config_region23(phba, rgn23_data);
+       else {
+               if_type = bf_get(lpfc_sli_intf_if_type,
+                                &phba->sli4_hba.sli_intf);
+               if (if_type == LPFC_SLI_INTF_IF_TYPE_0)
+                       goto out;
+               data_size = lpfc_sli4_get_config_region23(phba, rgn23_data);
+       }
 
        if (!data_size)
                goto out;
@@ -14830,9 +15674,8 @@ lpfc_sli_read_link_ste(struct lpfc_hba *phba)
                        goto out;
                }
        }
+
 out:
-       if (pmb)
-               mempool_free(pmb, phba->mbox_mem_pool);
        kfree(rgn23_data);
        return;
 }
@@ -14907,7 +15750,7 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
        else {
-               mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
+               mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
                rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
        }
        /* The IOCTL status is embedded in the mailbox subheader. */
index a0075b0af1423d76fbe32081ff654f0bd2284c2e..29c13b63e323563bf30009ed4205419de3a77775 100644 (file)
@@ -293,13 +293,11 @@ struct lpfc_sli {
        struct lpfc_lnk_stat lnk_stat_offsets;
 };
 
-#define LPFC_MBOX_TMO           30     /* Sec tmo for outstanding mbox
-                                          command */
-#define LPFC_MBOX_SLI4_CONFIG_TMO 60   /* Sec tmo for outstanding mbox
-                                          command */
-#define LPFC_MBOX_TMO_FLASH_CMD 300     /* Sec tmo for outstanding FLASH write
-                                        * or erase cmds. This is especially
-                                        * long because of the potential of
-                                        * multiple flash erases that can be
-                                        * spawned.
-                                        */
+/* Timeout for normal outstanding mbox command (Seconds) */
+#define LPFC_MBOX_TMO                          30
+/* Timeout for non-flash-based outstanding sli_config mbox command (Seconds) */
+#define LPFC_MBOX_SLI4_CONFIG_TMO              60
+/* Timeout for flash-based outstanding sli_config mbox command (Seconds) */
+#define LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO     300
+/* Timeout for other flash-based outstanding mbox command (Seconds) */
+#define LPFC_MBOX_TMO_FLASH_CMD                        300
index 88387c1c2dcc58238f3c26756ea2182980243bcc..92718820bee8c6e38558971f2a9de140a46d5e62 100644 (file)
@@ -23,7 +23,6 @@
 #define LPFC_XRI_EXCH_BUSY_WAIT_T1             10
 #define LPFC_XRI_EXCH_BUSY_WAIT_T2              30000
 #define LPFC_RELEASE_NOTIFICATION_INTERVAL     32
-#define LPFC_GET_QE_REL_INT                    32
 #define LPFC_RPI_LOW_WATER_MARK                        10
 
 #define LPFC_UNREG_FCF                          1
@@ -126,6 +125,8 @@ struct lpfc_queue {
        struct list_head child_list;
        uint32_t entry_count;   /* Number of entries to support on the queue */
        uint32_t entry_size;    /* Size of each queue entry. */
+       uint32_t entry_repost;  /* Count of entries before doorbell is rung */
+#define LPFC_QUEUE_MIN_REPOST  8
        uint32_t queue_id;      /* Queue ID assigned by the hardware */
        uint32_t assoc_qid;     /* Queue ID associated with, for CQ/WQ/MQ */
        struct list_head page_list;
@@ -159,6 +160,25 @@ struct lpfc_fcf_rec {
 #define RECORD_VALID   0x02
 };
 
+struct lpfc_fcf_pri_rec {
+       uint16_t fcf_index;
+#define LPFC_FCF_ON_PRI_LIST 0x0001
+#define LPFC_FCF_FLOGI_FAILED 0x0002
+       uint16_t flag;
+       uint32_t priority;
+};
+
+struct lpfc_fcf_pri {
+       struct list_head list;
+       struct lpfc_fcf_pri_rec fcf_rec;
+};
+
+/*
+ * Maximum FCF table index, it is for driver internal book keeping, it
+ * just needs to be no less than the supported HBA's FCF table size.
+ */
+#define LPFC_SLI4_FCF_TBL_INDX_MAX     32
+
 struct lpfc_fcf {
        uint16_t fcfi;
        uint32_t fcf_flag;
@@ -178,15 +198,13 @@ struct lpfc_fcf {
        uint32_t eligible_fcf_cnt;
        struct lpfc_fcf_rec current_rec;
        struct lpfc_fcf_rec failover_rec;
+       struct list_head fcf_pri_list;
+       struct lpfc_fcf_pri fcf_pri[LPFC_SLI4_FCF_TBL_INDX_MAX];
+       uint32_t current_fcf_scan_pri;
        struct timer_list redisc_wait;
        unsigned long *fcf_rr_bmask; /* Eligible FCF indexes for RR failover */
 };
 
-/*
- * Maximum FCF table index, it is for driver internal book keeping, it
- * just needs to be no less than the supported HBA's FCF table size.
- */
-#define LPFC_SLI4_FCF_TBL_INDX_MAX     32
 
 #define LPFC_REGION23_SIGNATURE "RG23"
 #define LPFC_REGION23_VERSION  1
@@ -371,6 +389,16 @@ struct lpfc_iov {
        uint32_t vf_number;
 };
 
+struct lpfc_sli4_lnk_info {
+       uint8_t lnk_dv;
+#define LPFC_LNK_DAT_INVAL     0
+#define LPFC_LNK_DAT_VAL       1
+       uint8_t lnk_tp;
+#define LPFC_LNK_GE    0x0 /* FCoE */
+#define LPFC_LNK_FC    0x1 /* FC   */
+       uint8_t lnk_no;
+};
+
 /* SLI4 HBA data structure entries */
 struct lpfc_sli4_hba {
        void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
@@ -392,7 +420,16 @@ struct lpfc_sli4_hba {
                        void __iomem *STATUSregaddr;
                        void __iomem *CTRLregaddr;
                        void __iomem *ERR1regaddr;
+#define SLIPORT_ERR1_REG_ERR_CODE_1            0x1
+#define SLIPORT_ERR1_REG_ERR_CODE_2            0x2
                        void __iomem *ERR2regaddr;
+#define SLIPORT_ERR2_REG_FW_RESTART            0x0
+#define SLIPORT_ERR2_REG_FUNC_PROVISON         0x1
+#define SLIPORT_ERR2_REG_FORCED_DUMP           0x2
+#define SLIPORT_ERR2_REG_FAILURE_EQ            0x3
+#define SLIPORT_ERR2_REG_FAILURE_CQ            0x4
+#define SLIPORT_ERR2_REG_FAILURE_BUS           0x5
+#define SLIPORT_ERR2_REG_FAILURE_RQ            0x6
                } if_type2;
        } u;
 
@@ -486,6 +523,10 @@ struct lpfc_sli4_hba {
        struct list_head sp_els_xri_aborted_work_queue;
        struct list_head sp_unsol_work_queue;
        struct lpfc_sli4_link link_state;
+       struct lpfc_sli4_lnk_info lnk_info;
+       uint32_t pport_name_sta;
+#define LPFC_SLI4_PPNAME_NON   0
+#define LPFC_SLI4_PPNAME_GET   1
        struct lpfc_iov iov;
        spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
        spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
@@ -536,6 +577,7 @@ struct lpfc_rsrc_blks {
  * SLI4 specific function prototypes
  */
 int lpfc_pci_function_reset(struct lpfc_hba *);
+int lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *);
 int lpfc_sli4_hba_setup(struct lpfc_hba *);
 int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t,
                     uint8_t, uint32_t, bool);
@@ -559,6 +601,7 @@ uint32_t lpfc_wq_create(struct lpfc_hba *, struct lpfc_queue *,
                        struct lpfc_queue *, uint32_t);
 uint32_t lpfc_rq_create(struct lpfc_hba *, struct lpfc_queue *,
                        struct lpfc_queue *, struct lpfc_queue *, uint32_t);
+void lpfc_rq_adjust_repost(struct lpfc_hba *, struct lpfc_queue *, int);
 uint32_t lpfc_eq_destroy(struct lpfc_hba *, struct lpfc_queue *);
 uint32_t lpfc_cq_destroy(struct lpfc_hba *, struct lpfc_queue *);
 uint32_t lpfc_mq_destroy(struct lpfc_hba *, struct lpfc_queue *);
@@ -615,5 +658,5 @@ void lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_sli4_unregister_fcf(struct lpfc_hba *);
 int lpfc_sli4_post_status_check(struct lpfc_hba *);
-uint8_t lpfc_sli4_mbox_opcode_get(struct lpfc_hba *, struct lpfcMboxq *);
-
+uint8_t lpfc_sli_config_mbox_subsys_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
+uint8_t lpfc_sli_config_mbox_opcode_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
index c03921b1232cdf944d00bf195c1a3a04ceeaffb1..8f000181233ba0daee50145963a293412b80a545 100644 (file)
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.23"
+#define LPFC_DRIVER_VERSION "8.3.5.58"
 #define LPFC_DRIVER_NAME               "lpfc"
 #define LPFC_SP_DRIVER_HANDLER_NAME    "lpfc:sp"
 #define LPFC_FP_DRIVER_HANDLER_NAME    "lpfc:fp"
 
 #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
                LPFC_DRIVER_VERSION
-#define LPFC_COPYRIGHT "Copyright(c) 2004-2009 Emulex.  All rights reserved."
+#define LPFC_COPYRIGHT "Copyright(c) 2004-2011 Emulex.  All rights reserved."
index 1feb551a57bce4cd8e8fe8cf0bb3c6522af3a154..a04cd048d7efb0ae82f61d3ca98b18feaac235d4 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2008 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -692,13 +692,14 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
                        /* Indicate free memory when release */
                        NLP_SET_FREE_REQ(ndlp);
                } else {
-                       if (!NLP_CHK_NODE_ACT(ndlp))
+                       if (!NLP_CHK_NODE_ACT(ndlp)) {
                                ndlp = lpfc_enable_node(vport, ndlp,
                                                NLP_STE_UNUSED_NODE);
                                if (!ndlp)
                                        goto skip_logo;
+                       }
 
-                       /* Remove ndlp from vport npld list */
+                       /* Remove ndlp from vport list */
                        lpfc_dequeue_node(vport, ndlp);
                        spin_lock_irq(&phba->ndlp_lock);
                        if (!NLP_CHK_FREE_REQ(ndlp))
@@ -711,8 +712,17 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
                        }
                        spin_unlock_irq(&phba->ndlp_lock);
                }
-               if (!(vport->vpi_state & LPFC_VPI_REGISTERED))
+
+               /*
+                * If the vpi is not registered, then a valid FDISC doesn't
+                * exist and there is no need for a ELS LOGO.  Just cleanup
+                * the ndlp.
+                */
+               if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) {
+                       lpfc_nlp_put(ndlp);
                        goto skip_logo;
+               }
+
                vport->unreg_vpi_cmpl = VPORT_INVAL;
                timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
                if (!lpfc_issue_els_npiv_logo(vport, ndlp))
@@ -764,10 +774,10 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba)
                return NULL;
        spin_lock_irq(&phba->hbalock);
        list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+               if (port_iterator->load_flag & FC_UNLOADING)
+                       continue;
                if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
-                       if (!(port_iterator->load_flag & FC_UNLOADING))
-                               lpfc_printf_vlog(port_iterator, KERN_ERR,
-                                        LOG_VPORT,
+                       lpfc_printf_vlog(port_iterator, KERN_ERR, LOG_VPORT,
                                         "1801 Create vport work array FAILED: "
                                         "cannot do scsi_host_get\n");
                        continue;