Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[cascardo/linux.git] / drivers / scsi / megaraid / megaraid_sas_base.c
index 3d95b16..4c3fc0e 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2003-2012  LSI Corporation.
+ *  Copyright (c) 2003-2013  LSI Corporation
+ *  Copyright (c) 2013-2014  Avago Technologies
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *
- *  FILE: megaraid_sas_base.c
- *  Version : 06.805.06.00-rc1
- *
- *  Authors: LSI Corporation
+ *  Authors: Avago Technologies
  *           Sreenivas Bagalkote
  *           Sumant Patro
  *           Bo Yang
  *           Sreenivas Bagalkote
  *           Sumant Patro
  *           Bo Yang
- *           Adam Radford <linuxraid@lsi.com>
+ *           Adam Radford
+ *           Kashyap Desai <kashyap.desai@avagotech.com>
+ *           Sumit Saxena <sumit.saxena@avagotech.com>
  *
  *
- *  Send feedback to: <megaraidlinux@lsi.com>
+ *  Send feedback to: megaraidlinux.pdl@avagotech.com
  *
  *
- *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- *     ATTN: Linuxraid
+ *  Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ *  San Jose, California 95131
  */
 
 #include <linux/kernel.h>
  */
 
 #include <linux/kernel.h>
@@ -79,7 +78,7 @@ static int allow_vf_ioctls;
 module_param(allow_vf_ioctls, int, S_IRUGO);
 MODULE_PARM_DESC(allow_vf_ioctls, "Allow ioctls in SR-IOV VF mode. Default: 0");
 
 module_param(allow_vf_ioctls, int, S_IRUGO);
 MODULE_PARM_DESC(allow_vf_ioctls, "Allow ioctls in SR-IOV VF mode. Default: 0");
 
-static int throttlequeuedepth = MEGASAS_THROTTLE_QUEUE_DEPTH;
+static unsigned int throttlequeuedepth = MEGASAS_THROTTLE_QUEUE_DEPTH;
 module_param(throttlequeuedepth, int, S_IRUGO);
 MODULE_PARM_DESC(throttlequeuedepth,
        "Adapter queue depth when throttled due to I/O timeout. Default: 16");
 module_param(throttlequeuedepth, int, S_IRUGO);
 MODULE_PARM_DESC(throttlequeuedepth,
        "Adapter queue depth when throttled due to I/O timeout. Default: 16");
@@ -1008,7 +1007,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
                cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
 
        cmd->sync_cmd = 1;
                cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
 
        cmd->sync_cmd = 1;
-       cmd->cmd_status = 0xFF;
+       cmd->cmd_status = ENODATA;
 
        instance->instancet->issue_dcmd(instance, cmd);
 
 
        instance->instancet->issue_dcmd(instance, cmd);
 
@@ -1418,16 +1417,15 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
 }
 
 /**
 }
 
 /**
- * megasas_is_ldio -           Checks if the cmd is for logical drive
+ * megasas_cmd_type -          Checks if the cmd is for logical drive/sysPD
+ *                             and whether it's RW or non RW
  * @scmd:                      SCSI command
  *
  * @scmd:                      SCSI command
  *
- * Called by megasas_queue_command to find out if the command to be queued
- * is a logical drive command
  */
  */
-inline int megasas_is_ldio(struct scsi_cmnd *cmd)
+inline int megasas_cmd_type(struct scsi_cmnd *cmd)
 {
 {
-       if (!MEGASAS_IS_LOGICAL(cmd))
-               return 0;
+       int ret;
+
        switch (cmd->cmnd[0]) {
        case READ_10:
        case WRITE_10:
        switch (cmd->cmnd[0]) {
        case READ_10:
        case WRITE_10:
@@ -1437,10 +1435,14 @@ inline int megasas_is_ldio(struct scsi_cmnd *cmd)
        case WRITE_6:
        case READ_16:
        case WRITE_16:
        case WRITE_6:
        case READ_16:
        case WRITE_16:
-               return 1;
+               ret = (MEGASAS_IS_LOGICAL(cmd)) ?
+                       READ_WRITE_LDIO : READ_WRITE_SYSPDIO;
+               break;
        default:
        default:
-               return 0;
+               ret = (MEGASAS_IS_LOGICAL(cmd)) ?
+                       NON_READ_WRITE_LDIO : NON_READ_WRITE_SYSPDIO;
        }
        }
+       return ret;
 }
 
  /**
 }
 
  /**
@@ -1472,7 +1474,7 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
                if(!cmd->scmd)
                        continue;
                printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr);
                if(!cmd->scmd)
                        continue;
                printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr);
-               if (megasas_is_ldio(cmd->scmd)){
+               if (megasas_cmd_type(cmd->scmd) == READ_WRITE_LDIO) {
                        ldio = (struct megasas_io_frame *)cmd->frame;
                        mfi_sgl = &ldio->sgl;
                        sgcount = ldio->sge_count;
                        ldio = (struct megasas_io_frame *)cmd->frame;
                        mfi_sgl = &ldio->sgl;
                        sgcount = ldio->sge_count;
@@ -1532,7 +1534,7 @@ megasas_build_and_issue_cmd(struct megasas_instance *instance,
        /*
         * Logical drive command
         */
        /*
         * Logical drive command
         */
-       if (megasas_is_ldio(scmd))
+       if (megasas_cmd_type(scmd) == READ_WRITE_LDIO)
                frame_count = megasas_build_ldio(instance, scmd, cmd);
        else
                frame_count = megasas_build_dcdb(instance, scmd, cmd);
                frame_count = megasas_build_ldio(instance, scmd, cmd);
        else
                frame_count = megasas_build_dcdb(instance, scmd, cmd);
@@ -1572,6 +1574,12 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
        instance = (struct megasas_instance *)
            scmd->device->host->hostdata;
 
        instance = (struct megasas_instance *)
            scmd->device->host->hostdata;
 
+       if (instance->unload == 1) {
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               return 0;
+       }
+
        if (instance->issuepend_done == 0)
                return SCSI_MLQUEUE_HOST_BUSY;
 
        if (instance->issuepend_done == 0)
                return SCSI_MLQUEUE_HOST_BUSY;
 
@@ -1684,22 +1692,66 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
        return 0;
 }
 
        return 0;
 }
 
+/*
+* megasas_complete_outstanding_ioctls - Complete outstanding ioctls after a
+*                                       kill adapter
+* @instance:                           Adapter soft state
+*
+*/
+void megasas_complete_outstanding_ioctls(struct megasas_instance *instance)
+{
+       int i;
+       struct megasas_cmd *cmd_mfi;
+       struct megasas_cmd_fusion *cmd_fusion;
+       struct fusion_context *fusion = instance->ctrl_context;
+
+       /* Find all outstanding ioctls */
+       if (fusion) {
+               for (i = 0; i < instance->max_fw_cmds; i++) {
+                       cmd_fusion = fusion->cmd_list[i];
+                       if (cmd_fusion->sync_cmd_idx != (u32)ULONG_MAX) {
+                               cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
+                               if (cmd_mfi->sync_cmd &&
+                                       cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT)
+                                       megasas_complete_cmd(instance,
+                                                            cmd_mfi, DID_OK);
+                       }
+               }
+       } else {
+               for (i = 0; i < instance->max_fw_cmds; i++) {
+                       cmd_mfi = instance->cmd_list[i];
+                       if (cmd_mfi->sync_cmd && cmd_mfi->frame->hdr.cmd !=
+                               MFI_CMD_ABORT)
+                               megasas_complete_cmd(instance, cmd_mfi, DID_OK);
+               }
+       }
+}
+
+
 void megaraid_sas_kill_hba(struct megasas_instance *instance)
 {
 void megaraid_sas_kill_hba(struct megasas_instance *instance)
 {
+       /* Set critical error to block I/O & ioctls in case caller didn't */
+       instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
+       /* Wait 1 second to ensure IO or ioctls in build have posted */
+       msleep(1000);
        if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
        if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
-               writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+               writel(MFI_STOP_ADP,
+                       &instance->reg_set->doorbell);
                /* Flush */
                readl(&instance->reg_set->doorbell);
                if (instance->mpio && instance->requestorId)
                        memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
        } else {
                /* Flush */
                readl(&instance->reg_set->doorbell);
                if (instance->mpio && instance->requestorId)
                        memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
        } else {
-               writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
+               writel(MFI_STOP_ADP,
+                       &instance->reg_set->inbound_doorbell);
        }
        }
+       /* Complete outstanding ioctls when adapter is killed */
+       megasas_complete_outstanding_ioctls(instance);
 }
 
  /**
 }
 
  /**
@@ -1712,6 +1764,7 @@ void
 megasas_check_and_restore_queue_depth(struct megasas_instance *instance)
 {
        unsigned long flags;
 megasas_check_and_restore_queue_depth(struct megasas_instance *instance)
 {
        unsigned long flags;
+
        if (instance->flag & MEGASAS_FW_BUSY
            && time_after(jiffies, instance->last_time + 5 * HZ)
            && atomic_read(&instance->fw_outstanding) <
        if (instance->flag & MEGASAS_FW_BUSY
            && time_after(jiffies, instance->last_time + 5 * HZ)
            && atomic_read(&instance->fw_outstanding) <
@@ -1719,13 +1772,8 @@ megasas_check_and_restore_queue_depth(struct megasas_instance *instance)
 
                spin_lock_irqsave(instance->host->host_lock, flags);
                instance->flag &= ~MEGASAS_FW_BUSY;
 
                spin_lock_irqsave(instance->host->host_lock, flags);
                instance->flag &= ~MEGASAS_FW_BUSY;
-               if (instance->is_imr) {
-                       instance->host->can_queue =
-                               instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
-               } else
-                       instance->host->can_queue =
-                               instance->max_fw_cmds - MEGASAS_INT_CMDS;
 
 
+               instance->host->can_queue = instance->max_scsi_cmds;
                spin_unlock_irqrestore(instance->host->host_lock, flags);
        }
 }
                spin_unlock_irqrestore(instance->host->host_lock, flags);
        }
 }
@@ -2586,20 +2634,6 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
        }
 }
 
        }
 }
 
-static int megasas_change_queue_depth(struct scsi_device *sdev,
-                                     int queue_depth, int reason)
-{
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
-       if (queue_depth > sdev->host->can_queue)
-               queue_depth = sdev->host->can_queue;
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev),
-                               queue_depth);
-
-       return queue_depth;
-}
-
 static ssize_t
 megasas_fw_crash_buffer_store(struct device *cdev,
        struct device_attribute *attr, const char *buf, size_t count)
 static ssize_t
 megasas_fw_crash_buffer_store(struct device *cdev,
        struct device_attribute *attr, const char *buf, size_t count)
@@ -2764,7 +2798,7 @@ static struct scsi_host_template megasas_template = {
        .shost_attrs = megaraid_host_attrs,
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = megaraid_host_attrs,
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
-       .change_queue_depth = megasas_change_queue_depth,
+       .change_queue_depth = scsi_change_queue_depth,
        .no_write_same = 1,
 };
 
        .no_write_same = 1,
 };
 
@@ -3037,10 +3071,9 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance)
                                        "was tried multiple times during reset."
                                        "Shutting down the HBA\n",
                                        cmd, cmd->scmd, cmd->sync_cmd);
                                        "was tried multiple times during reset."
                                        "Shutting down the HBA\n",
                                        cmd, cmd->scmd, cmd->sync_cmd);
+                               instance->instancet->disable_intr(instance);
+                               atomic_set(&instance->fw_reset_no_pci_access, 1);
                                megaraid_sas_kill_hba(instance);
                                megaraid_sas_kill_hba(instance);
-
-                               instance->adprecovery =
-                                               MEGASAS_HW_CRITICAL_ERROR;
                                return;
                        }
                }
                                return;
                        }
                }
@@ -3174,8 +3207,8 @@ process_fw_state_change_wq(struct work_struct *work)
                if (megasas_transition_to_ready(instance, 1)) {
                        printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
 
                if (megasas_transition_to_ready(instance, 1)) {
                        printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
 
+                       atomic_set(&instance->fw_reset_no_pci_access, 1);
                        megaraid_sas_kill_hba(instance);
                        megaraid_sas_kill_hba(instance);
-                       instance->adprecovery   = MEGASAS_HW_CRITICAL_ERROR;
                        return ;
                }
 
                        return ;
                }
 
@@ -3556,7 +3589,6 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
        int i;
        u32 max_cmd;
        u32 sge_sz;
        int i;
        u32 max_cmd;
        u32 sge_sz;
-       u32 sgl_sz;
        u32 total_sz;
        u32 frame_count;
        struct megasas_cmd *cmd;
        u32 total_sz;
        u32 frame_count;
        struct megasas_cmd *cmd;
@@ -3575,24 +3607,23 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
        }
 
        /*
        }
 
        /*
-        * Calculated the number of 64byte frames required for SGL
-        */
-       sgl_sz = sge_sz * instance->max_num_sge;
-       frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
-       frame_count = 15;
-
-       /*
-        * We need one extra frame for the MFI command
+        * For MFI controllers.
+        * max_num_sge = 60
+        * max_sge_sz  = 16 byte (sizeof megasas_sge_skinny)
+        * Total 960 byte (15 MFI frame of 64 byte)
+        *
+        * Fusion adapter require only 3 extra frame.
+        * max_num_sge = 16 (defined as MAX_IOCTL_SGE)
+        * max_sge_sz  = 12 byte (sizeof  megasas_sge64)
+        * Total 192 byte (3 MFI frame of 64 byte)
         */
         */
-       frame_count++;
-
+       frame_count = instance->ctrl_context ? (3 + 1) : (15 + 1);
        total_sz = MEGAMFI_FRAME_SIZE * frame_count;
        /*
         * Use DMA pool facility provided by PCI layer
         */
        instance->frame_dma_pool = pci_pool_create("megasas frame pool",
        total_sz = MEGAMFI_FRAME_SIZE * frame_count;
        /*
         * Use DMA pool facility provided by PCI layer
         */
        instance->frame_dma_pool = pci_pool_create("megasas frame pool",
-                                                  instance->pdev, total_sz, 64,
-                                                  0);
+                                       instance->pdev, total_sz, 256, 0);
 
        if (!instance->frame_dma_pool) {
                printk(KERN_DEBUG "megasas: failed to setup frame pool\n");
 
        if (!instance->frame_dma_pool) {
                printk(KERN_DEBUG "megasas: failed to setup frame pool\n");
@@ -4028,25 +4059,83 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
        return ret;
 }
 
        return ret;
 }
 
+/*
+ * megasas_update_ext_vd_details : Update details w.r.t Extended VD
+ * instance                     : Controller's instance
+*/
+static void megasas_update_ext_vd_details(struct megasas_instance *instance)
+{
+       struct fusion_context *fusion;
+       u32 old_map_sz;
+       u32 new_map_sz;
+
+       fusion = instance->ctrl_context;
+       /* For MFI based controllers return dummy success */
+       if (!fusion)
+               return;
+
+       instance->supportmax256vd =
+               instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
+       /* Below is additional check to address future FW enhancement */
+       if (instance->ctrl_info->max_lds > 64)
+               instance->supportmax256vd = 1;
+
+       instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
+                                       * MEGASAS_MAX_DEV_PER_CHANNEL;
+       instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
+                                       * MEGASAS_MAX_DEV_PER_CHANNEL;
+       if (instance->supportmax256vd) {
+               instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
+               instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+       } else {
+               instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
+               instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+       }
+       dev_info(&instance->pdev->dev, "Firmware supports %d VD %d PD\n",
+               instance->fw_supported_vd_count,
+               instance->fw_supported_pd_count);
+       dev_info(&instance->pdev->dev, "Driver supports %d VD  %d PD\n",
+               instance->drv_supported_vd_count,
+               instance->drv_supported_pd_count);
+
+       old_map_sz =  sizeof(struct MR_FW_RAID_MAP) +
+                               (sizeof(struct MR_LD_SPAN_MAP) *
+                               (instance->fw_supported_vd_count - 1));
+       new_map_sz =  sizeof(struct MR_FW_RAID_MAP_EXT);
+       fusion->drv_map_sz =  sizeof(struct MR_DRV_RAID_MAP) +
+                               (sizeof(struct MR_LD_SPAN_MAP) *
+                               (instance->drv_supported_vd_count - 1));
+
+       fusion->max_map_sz = max(old_map_sz, new_map_sz);
+
+
+       if (instance->supportmax256vd)
+               fusion->current_map_sz = new_map_sz;
+       else
+               fusion->current_map_sz = old_map_sz;
+
+}
+
 /**
  * megasas_get_controller_info -       Returns FW's controller structure
  * @instance:                          Adapter soft state
 /**
  * megasas_get_controller_info -       Returns FW's controller structure
  * @instance:                          Adapter soft state
- * @ctrl_info:                         Controller information structure
  *
  * Issues an internal command (DCMD) to get the FW's controller structure.
  * This information is mainly used to find out the maximum IO transfer per
  * command supported by the FW.
  */
 int
  *
  * Issues an internal command (DCMD) to get the FW's controller structure.
  * This information is mainly used to find out the maximum IO transfer per
  * command supported by the FW.
  */
 int
-megasas_get_ctrl_info(struct megasas_instance *instance,
-                     struct megasas_ctrl_info *ctrl_info)
+megasas_get_ctrl_info(struct megasas_instance *instance)
 {
        int ret = 0;
        struct megasas_cmd *cmd;
        struct megasas_dcmd_frame *dcmd;
        struct megasas_ctrl_info *ci;
 {
        int ret = 0;
        struct megasas_cmd *cmd;
        struct megasas_dcmd_frame *dcmd;
        struct megasas_ctrl_info *ci;
+       struct megasas_ctrl_info *ctrl_info;
        dma_addr_t ci_h = 0;
 
        dma_addr_t ci_h = 0;
 
+       ctrl_info = instance->ctrl_info;
+
        cmd = megasas_get_cmd(instance);
 
        if (!cmd) {
        cmd = megasas_get_cmd(instance);
 
        if (!cmd) {
@@ -4086,8 +4175,13 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
        else
                ret = megasas_issue_polled(instance, cmd);
 
        else
                ret = megasas_issue_polled(instance, cmd);
 
-       if (!ret)
+       if (!ret) {
                memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
                memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
+               le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
+               le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
+               le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
+               megasas_update_ext_vd_details(instance);
+       }
 
        pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
                            ci, ci_h);
 
        pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
                            ci, ci_h);
@@ -4289,7 +4383,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
        if (megasas_issue_init_mfi(instance))
                goto fail_fw_init;
 
        if (megasas_issue_init_mfi(instance))
                goto fail_fw_init;
 
-       if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
+       if (megasas_get_ctrl_info(instance)) {
                dev_err(&instance->pdev->dev, "(%d): Could get controller info "
                        "Fail from %s %d\n", instance->unique_id,
                        __func__, __LINE__);
                dev_err(&instance->pdev->dev, "(%d): Could get controller info "
                        "Fail from %s %d\n", instance->unique_id,
                        __func__, __LINE__);
@@ -4527,12 +4621,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
                dev_info(&instance->pdev->dev,
                        "Controller type: iMR\n");
        }
                dev_info(&instance->pdev->dev,
                        "Controller type: iMR\n");
        }
-       /* OnOffProperties are converted into CPU arch*/
-       le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
        instance->disableOnlineCtrlReset =
        ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
        instance->disableOnlineCtrlReset =
        ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
-       /* adapterOperations2 are converted into CPU arch*/
-       le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
        instance->mpio = ctrl_info->adapterOperations2.mpio;
        instance->UnevenSpanSupport =
                ctrl_info->adapterOperations2.supportUnevenSpans;
        instance->mpio = ctrl_info->adapterOperations2.mpio;
        instance->UnevenSpanSupport =
                ctrl_info->adapterOperations2.supportUnevenSpans;
@@ -4562,7 +4652,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
                       "requestorId %d\n", instance->requestorId);
        }
 
                       "requestorId %d\n", instance->requestorId);
        }
 
-       le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
        instance->crash_dump_fw_support =
                ctrl_info->adapterOperations3.supportCrashDump;
        instance->crash_dump_drv_support =
        instance->crash_dump_fw_support =
                ctrl_info->adapterOperations3.supportCrashDump;
        instance->crash_dump_drv_support =
@@ -4582,29 +4671,47 @@ static int megasas_init_fw(struct megasas_instance *instance)
                                instance->crash_dump_h);
                instance->crash_dump_buf = NULL;
        }
                                instance->crash_dump_h);
                instance->crash_dump_buf = NULL;
        }
+
+       instance->secure_jbod_support =
+               ctrl_info->adapterOperations3.supportSecurityonJBOD;
+       if (instance->secure_jbod_support)
+               dev_info(&instance->pdev->dev, "Firmware supports Secure JBOD\n");
        instance->max_sectors_per_req = instance->max_num_sge *
                                                PAGE_SIZE / 512;
        if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
                instance->max_sectors_per_req = tmp_sectors;
 
        instance->max_sectors_per_req = instance->max_num_sge *
                                                PAGE_SIZE / 512;
        if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
                instance->max_sectors_per_req = tmp_sectors;
 
-       kfree(ctrl_info);
+       /*
+        * 1. For fusion adapters, 3 commands for IOCTL and 5 commands
+        *    for driver's internal DCMDs.
+        * 2. For MFI skinny adapters, 5 commands for IOCTL + driver's
+        *    internal DCMDs.
+        * 3. For rest of MFI adapters, 27 commands reserved for IOCTLs
+        *    and 5 commands for drivers's internal DCMD.
+        */
+       if (instance->ctrl_context) {
+               instance->max_scsi_cmds = instance->max_fw_cmds -
+                                       (MEGASAS_FUSION_INTERNAL_CMDS +
+                                       MEGASAS_FUSION_IOCTL_CMDS);
+               sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS);
+       } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+               instance->max_scsi_cmds = instance->max_fw_cmds -
+                                               MEGASAS_SKINNY_INT_CMDS;
+               sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
+       } else {
+               instance->max_scsi_cmds = instance->max_fw_cmds -
+                                               MEGASAS_INT_CMDS;
+               sema_init(&instance->ioctl_sem, (MEGASAS_INT_CMDS - 5));
+       }
 
        /* Check for valid throttlequeuedepth module parameter */
 
        /* Check for valid throttlequeuedepth module parameter */
-       if (instance->is_imr) {
-               if (throttlequeuedepth > (instance->max_fw_cmds -
-                                         MEGASAS_SKINNY_INT_CMDS))
-                       instance->throttlequeuedepth =
-                               MEGASAS_THROTTLE_QUEUE_DEPTH;
-               else
-                       instance->throttlequeuedepth = throttlequeuedepth;
-       } else {
-               if (throttlequeuedepth > (instance->max_fw_cmds -
-                                         MEGASAS_INT_CMDS))
-                       instance->throttlequeuedepth =
+       if (throttlequeuedepth &&
+                       throttlequeuedepth <= instance->max_scsi_cmds)
+               instance->throttlequeuedepth = throttlequeuedepth;
+       else
+               instance->throttlequeuedepth =
                                MEGASAS_THROTTLE_QUEUE_DEPTH;
                                MEGASAS_THROTTLE_QUEUE_DEPTH;
-               else
-                       instance->throttlequeuedepth = throttlequeuedepth;
-       }
 
         /*
        * Setup tasklet for cmd completion
 
         /*
        * Setup tasklet for cmd completion
@@ -4900,12 +5007,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
         */
        host->irq = instance->pdev->irq;
        host->unique_id = instance->unique_id;
         */
        host->irq = instance->pdev->irq;
        host->unique_id = instance->unique_id;
-       if (instance->is_imr) {
-               host->can_queue =
-                       instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
-       } else
-               host->can_queue =
-                       instance->max_fw_cmds - MEGASAS_INT_CMDS;
+       host->can_queue = instance->max_scsi_cmds;
        host->this_id = instance->init_id;
        host->sg_tablesize = instance->max_num_sge;
 
        host->this_id = instance->init_id;
        host->sg_tablesize = instance->max_num_sge;
 
@@ -4957,10 +5059,6 @@ static int megasas_io_attach(struct megasas_instance *instance)
                return -ENODEV;
        }
 
                return -ENODEV;
        }
 
-       /*
-        * Trigger SCSI to scan our drives
-        */
-       scsi_scan_host(host);
        return 0;
 }
 
        return 0;
 }
 
@@ -5083,10 +5181,10 @@ static int megasas_probe_one(struct pci_dev *pdev,
                        goto fail_alloc_dma_buf;
                }
                fusion = instance->ctrl_context;
                        goto fail_alloc_dma_buf;
                }
                fusion = instance->ctrl_context;
+               memset(fusion, 0,
+                       ((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
                INIT_LIST_HEAD(&fusion->cmd_pool);
                spin_lock_init(&fusion->mpt_pool_lock);
                INIT_LIST_HEAD(&fusion->cmd_pool);
                spin_lock_init(&fusion->mpt_pool_lock);
-               memset(fusion->load_balance_info, 0,
-                       sizeof(struct LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT);
        }
        break;
        default: /* For all other supported controllers */
        }
        break;
        default: /* For all other supported controllers */
@@ -5170,12 +5268,10 @@ static int megasas_probe_one(struct pci_dev *pdev,
        instance->init_id = MEGASAS_DEFAULT_INIT_ID;
        instance->ctrl_info = NULL;
 
        instance->init_id = MEGASAS_DEFAULT_INIT_ID;
        instance->ctrl_info = NULL;
 
+
        if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
        if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
                instance->flag_ieee = 1;
                instance->flag_ieee = 1;
-               sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
-       } else
-               sema_init(&instance->ioctl_sem, (MEGASAS_INT_CMDS - 5));
 
        megasas_dbg_lvl = 0;
        instance->flag = 0;
 
        megasas_dbg_lvl = 0;
        instance->flag = 0;
@@ -5288,6 +5384,10 @@ retry_irq_register:
                goto fail_io_attach;
 
        instance->unload = 0;
                goto fail_io_attach;
 
        instance->unload = 0;
+       /*
+        * Trigger SCSI to scan our drives
+        */
+       scsi_scan_host(host);
 
        /*
         * Initiate AEN (Asynchronous Event Notification)
 
        /*
         * Initiate AEN (Asynchronous Event Notification)
@@ -6051,6 +6151,11 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        megasas_issue_blocked_cmd(instance, cmd, 0);
        cmd->sync_cmd = 0;
 
        megasas_issue_blocked_cmd(instance, cmd, 0);
        cmd->sync_cmd = 0;
 
+       if (instance->unload == 1) {
+               dev_info(&instance->pdev->dev, "Driver unload is in progress "
+                       "don't submit data to application\n");
+               goto out;
+       }
        /*
         * copy out the kernel buffers to user buffers
         */
        /*
         * copy out the kernel buffers to user buffers
         */
@@ -6161,9 +6266,6 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
                goto out_kfree_ioc;
        }
 
                goto out_kfree_ioc;
        }
 
-       /*
-        * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
-        */
        if (down_interruptible(&instance->ioctl_sem)) {
                error = -ERESTARTSYS;
                goto out_kfree_ioc;
        if (down_interruptible(&instance->ioctl_sem)) {
                error = -ERESTARTSYS;
                goto out_kfree_ioc;
@@ -6399,16 +6501,6 @@ static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
 
 static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
 
 
 static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
 
-static ssize_t
-megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
-{
-       return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
-                       MEGASAS_RELDATE);
-}
-
-static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
-                  NULL);
-
 static ssize_t
 megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
 {
 static ssize_t
 megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
 {
@@ -6712,8 +6804,7 @@ static int __init megasas_init(void)
        /*
         * Announce driver version and other information
         */
        /*
         * Announce driver version and other information
         */
-       printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
-              MEGASAS_EXT_VERSION);
+       pr_info("megasas: %s\n", MEGASAS_VERSION);
 
        spin_lock_init(&poll_aen_lock);
 
 
        spin_lock_init(&poll_aen_lock);
 
@@ -6748,10 +6839,6 @@ static int __init megasas_init(void)
                                  &driver_attr_version);
        if (rval)
                goto err_dcf_attr_ver;
                                  &driver_attr_version);
        if (rval)
                goto err_dcf_attr_ver;
-       rval = driver_create_file(&megasas_pci_driver.driver,
-                                 &driver_attr_release_date);
-       if (rval)
-               goto err_dcf_rel_date;
 
        rval = driver_create_file(&megasas_pci_driver.driver,
                                &driver_attr_support_poll_for_event);
 
        rval = driver_create_file(&megasas_pci_driver.driver,
                                &driver_attr_support_poll_for_event);
@@ -6775,12 +6862,7 @@ err_dcf_support_device_change:
 err_dcf_dbg_lvl:
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_poll_for_event);
 err_dcf_dbg_lvl:
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_poll_for_event);
-
 err_dcf_support_poll_for_event:
 err_dcf_support_poll_for_event:
-       driver_remove_file(&megasas_pci_driver.driver,
-                          &driver_attr_release_date);
-
-err_dcf_rel_date:
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 err_dcf_attr_ver:
        pci_unregister_driver(&megasas_pci_driver);
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 err_dcf_attr_ver:
        pci_unregister_driver(&megasas_pci_driver);
@@ -6800,8 +6882,6 @@ static void __exit megasas_exit(void)
                        &driver_attr_support_poll_for_event);
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_device_change);
                        &driver_attr_support_poll_for_event);
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_device_change);
-       driver_remove_file(&megasas_pci_driver.driver,
-                          &driver_attr_release_date);
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 
        pci_unregister_driver(&megasas_pci_driver);
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 
        pci_unregister_driver(&megasas_pci_driver);