Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[pandora-kernel.git] / drivers / scsi / lpfc / lpfc_debugfs.c
index 30b25c5..a0424dd 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
 /*
@@ -135,7 +136,11 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
        int i, index, len, enable;
        uint32_t ms;
        struct lpfc_debugfs_trc *dtp;
-       char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
+       char *buffer;
+
+       buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
+       if (!buffer)
+               return 0;
 
        enable = lpfc_debugfs_enable;
        lpfc_debugfs_enable = 0;
@@ -167,6 +172,8 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
        }
 
        lpfc_debugfs_enable = enable;
+       kfree(buffer);
+
        return len;
 }
 
@@ -195,8 +202,11 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
        int i, index, len, enable;
        uint32_t ms;
        struct lpfc_debugfs_trc *dtp;
-       char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
+       char *buffer;
 
+       buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL);
+       if (!buffer)
+               return 0;
 
        enable = lpfc_debugfs_enable;
        lpfc_debugfs_enable = 0;
@@ -228,6 +238,8 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
        }
 
        lpfc_debugfs_enable = enable;
+       kfree(buffer);
+
        return len;
 }
 
@@ -378,7 +390,11 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
        int len = 0;
        int i, off;
        uint32_t *ptr;
-       char buffer[1024];
+       char *buffer;
+
+       buffer = kmalloc(1024, GFP_KERNEL);
+       if (!buffer)
+               return 0;
 
        off = 0;
        spin_lock_irq(&phba->hbalock);
@@ -407,6 +423,8 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
        }
 
        spin_unlock_irq(&phba->hbalock);
+       kfree(buffer);
+
        return len;
 }
 
@@ -1327,8 +1345,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;
 
@@ -1373,6 +1391,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,
@@ -1385,8 +1408,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);
@@ -1439,8 +1465,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;
@@ -1475,9 +1501,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)) &&
@@ -1569,6 +1595,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.
@@ -1871,8 +2183,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;
@@ -1944,12 +2256,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 ||
@@ -2218,7 +2530,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;
 
@@ -2257,7 +2569,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;
 
@@ -2269,8 +2581,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 ||
@@ -2330,63 +2642,736 @@ 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;
 
-#undef lpfc_debugfs_op_hbqinfo
-static const struct file_operations lpfc_debugfs_op_hbqinfo = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_hbqinfo_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+       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;
+}
 
-#undef lpfc_debugfs_op_dumpHBASlim
-static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_dumpHBASlim_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+/**
+ * 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;
 
-#undef lpfc_debugfs_op_dumpHostSlim
-static const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_dumpHostSlim_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .release =      lpfc_debugfs_release,
-};
+       /* This is a user read operation */
+       debug->op = LPFC_IDIAG_OP_RD;
 
-#undef lpfc_debugfs_op_dumpData
-static const struct file_operations lpfc_debugfs_op_dumpData = {
-       .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_dumpData_open,
-       .llseek =       lpfc_debugfs_lseek,
-       .read =         lpfc_debugfs_read,
-       .write =        lpfc_debugfs_dumpDataDif_write,
-       .release =      lpfc_debugfs_dumpDataDif_release,
-};
+       if (!debug->buffer)
+               debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL);
+       if (!debug->buffer)
+               return 0;
+       pbuffer = debug->buffer;
 
-#undef lpfc_debugfs_op_dumpDif
-static const struct file_operations lpfc_debugfs_op_dumpDif = {
+       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
+static const struct file_operations lpfc_debugfs_op_hbqinfo = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_hbqinfo_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_dumpHBASlim
+static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_dumpHBASlim_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_dumpHostSlim
+static const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_dumpHostSlim_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .release =      lpfc_debugfs_release,
+};
+
+#undef lpfc_debugfs_op_dumpData
+static const struct file_operations lpfc_debugfs_op_dumpData = {
+       .owner =        THIS_MODULE,
+       .open =         lpfc_debugfs_dumpData_open,
+       .llseek =       lpfc_debugfs_lseek,
+       .read =         lpfc_debugfs_read,
+       .write =        lpfc_debugfs_dumpDataDif_write,
+       .release =      lpfc_debugfs_dumpDataDif_release,
+};
+
+#undef lpfc_debugfs_op_dumpDif
+static const struct file_operations lpfc_debugfs_op_dumpDif = {
        .owner =        THIS_MODULE,
        .open =         lpfc_debugfs_dumpDif_open,
        .llseek =       lpfc_debugfs_lseek,
@@ -2420,6 +3405,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,
@@ -2428,7 +3423,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,
@@ -2438,7 +3433,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,
@@ -2448,8 +3443,234 @@ 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
  * @vport: The vport pointer to initialize.
@@ -2673,7 +3894,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;
        }
 
@@ -2710,6 +3931,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) {
@@ -2749,6 +3984,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
@@ -2783,7 +4062,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;
@@ -2827,6 +4105,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);
@@ -2842,6 +4135,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);