Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[pandora-kernel.git] / drivers / scsi / mpt2sas / mpt2sas_scsih.c
index a7dbc68..6abd2fc 100644 (file)
@@ -94,6 +94,10 @@ static u32 logging_level;
 MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
     "(default=0)");
 
+static ushort max_sectors = 0xFFFF;
+module_param(max_sectors, ushort, 0);
+MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 8192  default=8192");
+
 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
 #define MPT2SAS_MAX_LUN (16895)
 static int max_lun = MPT2SAS_MAX_LUN;
@@ -1956,7 +1960,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
                case MPI2_RAID_VOL_TYPE_RAID1E:
                        qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
                        if (ioc->manu_pg10.OEMIdentifier &&
-                           (ioc->manu_pg10.GenericFlags0 &
+                           (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
                            MFG10_GF0_R10_DISPLAY) &&
                            !(raid_device->num_pds % 2))
                                r_level = "RAID10";
@@ -2236,6 +2240,8 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
  * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
  * @smid_task: smid assigned to the task
  * @timeout: timeout in seconds
+ * @serial_number: the serial_number from scmd
+ * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
  * Context: user
  *
  * A generic API for sending task management requests to firmware.
@@ -2247,17 +2253,18 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
 int
 mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
     uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
-    struct scsi_cmnd *scmd)
+       unsigned long serial_number, enum mutex_type m_type)
 {
        Mpi2SCSITaskManagementRequest_t *mpi_request;
        Mpi2SCSITaskManagementReply_t *mpi_reply;
        u16 smid = 0;
        u32 ioc_state;
        unsigned long timeleft;
-       struct scsi_cmnd *scmd_lookup;
+       struct scsiio_tracker *scsi_lookup = NULL;
        int rc;
 
-       mutex_lock(&ioc->tm_cmds.mutex);
+       if (m_type == TM_MUTEX_ON)
+               mutex_lock(&ioc->tm_cmds.mutex);
        if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
                printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
                    __func__, ioc->name);
@@ -2277,18 +2284,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
        if (ioc_state & MPI2_DOORBELL_USED) {
                dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
                    "active!\n", ioc->name));
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+               rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
                    FORCE_BIG_HAMMER);
-               rc = SUCCESS;
+               rc = (!rc) ? SUCCESS : FAILED;
                goto err_out;
        }
 
        if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
                mpt2sas_base_fault_info(ioc, ioc_state &
                    MPI2_DOORBELL_DATA_MASK);
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+               rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
                    FORCE_BIG_HAMMER);
-               rc = SUCCESS;
+               rc = (!rc) ? SUCCESS : FAILED;
                goto err_out;
        }
 
@@ -2300,6 +2307,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
                goto err_out;
        }
 
+       if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+               scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
+
        dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
            " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
            smid_task));
@@ -2307,6 +2317,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
        ioc->tm_cmds.smid = smid;
        memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+       memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
        mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
        mpi_request->DevHandle = cpu_to_le16(handle);
        mpi_request->TaskType = type;
@@ -2322,9 +2333,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
                _debug_dump_mf(mpi_request,
                    sizeof(Mpi2SCSITaskManagementRequest_t)/4);
                if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
-                       mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+                       rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
                            FORCE_BIG_HAMMER);
-                       rc = SUCCESS;
+                       rc = (!rc) ? SUCCESS : FAILED;
                        ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
                        mpt2sas_scsih_clear_tm_flag(ioc, handle);
                        goto err_out;
@@ -2346,20 +2357,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
                }
        }
 
-       /* sanity check:
-        * Check to see the commands were terminated.
-        * This is only needed for eh callbacks, hence the scmd check.
-        */
-       rc = FAILED;
-       if (scmd == NULL)
-               goto bypass_sanity_checks;
        switch (type) {
        case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
-               scmd_lookup = _scsih_scsi_lookup_get(ioc, smid_task);
-               if (scmd_lookup)
-                       rc = FAILED;
-               else
-                       rc = SUCCESS;
+               rc = SUCCESS;
+               if (scsi_lookup->scmd == NULL)
+                       break;
+               rc = FAILED;
                break;
 
        case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2369,24 +2372,31 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
                        rc = SUCCESS;
                break;
 
+       case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
        case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
                if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
                        rc = FAILED;
                else
                        rc = SUCCESS;
                break;
+       case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
+               rc = SUCCESS;
+               break;
+       default:
+               rc = FAILED;
+               break;
        }
 
- bypass_sanity_checks:
-
        mpt2sas_scsih_clear_tm_flag(ioc, handle);
        ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_unlock(&ioc->tm_cmds.mutex);
+       if (m_type == TM_MUTEX_ON)
+               mutex_unlock(&ioc->tm_cmds.mutex);
 
        return rc;
 
  err_out:
-       mutex_unlock(&ioc->tm_cmds.mutex);
+       if (m_type == TM_MUTEX_ON)
+               mutex_unlock(&ioc->tm_cmds.mutex);
        return rc;
 }
 
@@ -2496,7 +2506,8 @@ _scsih_abort(struct scsi_cmnd *scmd)
        handle = sas_device_priv_data->sas_target->handle;
        r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
            scmd->device->id, scmd->device->lun,
-           MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, scmd);
+           MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
+           scmd->serial_number, TM_MUTEX_ON);
 
  out:
        sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
@@ -2557,7 +2568,8 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
 
        r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
            scmd->device->id, scmd->device->lun,
-           MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, scmd);
+           MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
+           TM_MUTEX_ON);
 
  out:
        sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
@@ -2617,7 +2629,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
 
        r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
            scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
-           30, scmd);
+           30, 0, TM_MUTEX_ON);
 
  out:
        starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
@@ -2749,6 +2761,31 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
        }
 }
 
+/**
+ * _scsih_ublock_io_all_device - unblock every device
+ * @ioc: per adapter object
+ *
+ * change the device state from block to running
+ */
+static void
+_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+       struct MPT2SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (!sas_device_priv_data->block)
+                       continue;
+               sas_device_priv_data->block = 0;
+               dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
+                   "handle(0x%04x)\n",
+                   sas_device_priv_data->sas_target->handle));
+               scsi_internal_device_unblock(sdev);
+       }
+}
 /**
  * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
  * @ioc: per adapter object
@@ -2778,6 +2815,34 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        }
 }
 
+/**
+ * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+       struct MPT2SAS_DEVICE *sas_device_priv_data;
+       struct scsi_device *sdev;
+
+       shost_for_each_device(sdev, ioc->shost) {
+               sas_device_priv_data = sdev->hostdata;
+               if (!sas_device_priv_data)
+                       continue;
+               if (sas_device_priv_data->block)
+                       continue;
+               sas_device_priv_data->block = 1;
+               dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
+                   "handle(0x%04x)\n",
+                   sas_device_priv_data->sas_target->handle));
+               scsi_internal_device_block(sdev);
+       }
+}
+
+
 /**
  * _scsih_block_io_device - set the device state to SDEV_BLOCK
  * @ioc: per adapter object
@@ -3698,7 +3763,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
                return 0;
        }
 
-       if (ioc->pci_error_recovery) {
+       if (ioc->pci_error_recovery || ioc->remove_host) {
                scmd->result = DID_NO_CONNECT << 16;
                scmd->scsi_done(scmd);
                return 0;
@@ -4193,6 +4258,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        u32 log_info;
        struct MPT2SAS_DEVICE *sas_device_priv_data;
        u32 response_code = 0;
+       unsigned long flags;
 
        mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
        scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
@@ -4217,6 +4283,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
         * the failed direct I/O should be redirected to volume
         */
        if (_scsih_scsi_direct_io_get(ioc, smid)) {
+               spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+               ioc->scsi_lookup[smid - 1].scmd = scmd;
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
                _scsih_scsi_direct_io_set(ioc, smid, 0);
                memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
                mpi_request->DevHandle =
@@ -4598,7 +4667,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        Mpi2SasEnclosurePage0_t enclosure_pg0;
        u32 ioc_status;
        u16 parent_handle;
-       __le64 sas_address, sas_address_parent = 0;
+       u64 sas_address, sas_address_parent = 0;
        int i;
        unsigned long flags;
        struct _sas_port *mpt2sas_port = NULL;
@@ -5380,9 +5449,10 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
                break;
        }
        printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
-           "\thandle(0x%04x), sas address(0x%016llx)", ioc->name,
-           reason_str, le16_to_cpu(event_data->DevHandle),
-           (unsigned long long)le64_to_cpu(event_data->SASAddress));
+           "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
+           ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
+           (unsigned long long)le64_to_cpu(event_data->SASAddress),
+           le16_to_cpu(event_data->TaskTag));
        if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
                printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
                    event_data->ASC, event_data->ASCQ);
@@ -5404,7 +5474,7 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
 {
        struct MPT2SAS_TARGET *target_priv_data;
        struct _sas_device *sas_device;
-       __le64 sas_address;
+       u64 sas_address;
        unsigned long flags;
        Mpi2EventDataSasDeviceStatusChange_t *event_data =
            fw_event->event_data;
@@ -5522,25 +5592,38 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
        u32 termination_count;
        u32 query_count;
        Mpi2SCSITaskManagementReply_t *mpi_reply;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
-#endif
        u16 ioc_status;
        unsigned long flags;
        int r;
+       u8 max_retries = 0;
+       u8 task_abort_retries;
+
+       mutex_lock(&ioc->tm_cmds.mutex);
+       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
+           "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
+            event_data->PortWidth));
 
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: "
-           "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
-           event_data->PortWidth));
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-           __func__));
+       _scsih_block_io_all_device(ioc);
 
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       ioc->broadcast_aen_busy = 0;
+       mpi_reply = ioc->tm_cmds.reply;
+broadcast_aen_retry:
+
+       /* sanity checks for retrying this loop */
+       if (max_retries++ == 5) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
+                   ioc->name, __func__));
+               goto out;
+       } else if (max_retries > 1)
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
+                   ioc->name, __func__, max_retries - 1));
+
        termination_count = 0;
        query_count = 0;
-       mpi_reply = ioc->tm_cmds.reply;
        for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+               if (ioc->ioc_reset_in_progress_status)
+                       goto out;
                scmd = _scsih_scsi_lookup_get(ioc, smid);
                if (!scmd)
                        continue;
@@ -5561,34 +5644,90 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
                lun = sas_device_priv_data->lun;
                query_count++;
 
+               if (ioc->ioc_reset_in_progress_status)
+                       goto out;
+
                spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-               mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
-                   MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL);
-               ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+               r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
+                   MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
+                   TM_MUTEX_OFF);
+               if (r == FAILED) {
+                       sdev_printk(KERN_WARNING, sdev,
+                           "mpt2sas_scsih_issue_tm: FAILED when sending "
+                           "QUERY_TASK: scmd(%p)\n", scmd);
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+                       goto broadcast_aen_retry;
+               }
                ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
                    & MPI2_IOCSTATUS_MASK;
-               if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
-                   (mpi_reply->ResponseCode ==
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
+                           "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
+                           scmd);
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+                       goto broadcast_aen_retry;
+               }
+
+               /* see if IO is still owned by IOC and target */
+               if (mpi_reply->ResponseCode ==
                     MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
                     mpi_reply->ResponseCode ==
-                    MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) {
+                    MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
                        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
                        continue;
                }
+               task_abort_retries = 0;
+ tm_retry:
+               if (task_abort_retries++ == 60) {
+                       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+                           "%s: ABORT_TASK: giving up\n", ioc->name,
+                           __func__));
+                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+                       goto broadcast_aen_retry;
+               }
+
+               if (ioc->ioc_reset_in_progress_status)
+                       goto out_no_lock;
+
                r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
                    sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
-                   scmd);
-               if (r == FAILED)
-                       sdev_printk(KERN_WARNING, sdev, "task abort: FAILED "
+                   scmd->serial_number, TM_MUTEX_OFF);
+               if (r == FAILED) {
+                       sdev_printk(KERN_WARNING, sdev,
+                           "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
                            "scmd(%p)\n", scmd);
+                       goto tm_retry;
+               }
+
+               if (task_abort_retries > 1)
+                       sdev_printk(KERN_WARNING, sdev,
+                           "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
+                           " scmd(%p)\n",
+                           task_abort_retries - 1, scmd);
+
                termination_count += le32_to_cpu(mpi_reply->TerminationCount);
                spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
        }
+
+       if (ioc->broadcast_aen_pending) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
+                    " pending AEN\n", ioc->name, __func__));
+                ioc->broadcast_aen_pending = 0;
+                goto broadcast_aen_retry;
+       }
+
+ out:
        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ out_no_lock:
 
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
+       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
            "%s - exit, query_count = %d termination_count = %d\n",
            ioc->name, __func__, query_count, termination_count));
+
+       ioc->broadcast_aen_busy = 0;
+       if (!ioc->ioc_reset_in_progress_status)
+               _scsih_ublock_io_all_device(ioc);
+       mutex_unlock(&ioc->tm_cmds.mutex);
 }
 
 /**
@@ -6566,7 +6705,7 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
        Mpi2ExpanderPage0_t expander_pg0;
        Mpi2ConfigReply_t mpi_reply;
        u16 ioc_status;
-       __le64 sas_address;
+       u64 sas_address;
        u16 handle;
 
        printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
@@ -6862,10 +7001,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
                    mpi_reply->EventData;
 
                if (baen_data->Primitive !=
-                   MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
-                   ioc->broadcast_aen_busy)
+                   MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
                        return 1;
-               ioc->broadcast_aen_busy = 1;
+
+               if (ioc->broadcast_aen_busy) {
+                       ioc->broadcast_aen_pending++;
+                       return 1;
+               } else
+                       ioc->broadcast_aen_busy = 1;
                break;
        }
 
@@ -7211,7 +7354,6 @@ _scsih_remove(struct pci_dev *pdev)
        }
 
        sas_remove_host(shost);
-       _scsih_shutdown(pdev);
        list_del(&ioc->list);
        scsi_remove_host(shost);
        scsi_host_put(shost);
@@ -7436,6 +7578,25 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        shost->transportt = mpt2sas_transport_template;
        shost->unique_id = ioc->id;
 
+       if (max_sectors != 0xFFFF) {
+               if (max_sectors < 64) {
+                       shost->max_sectors = 64;
+                       printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+                           "for max_sectors, range is 64 to 8192. Assigning "
+                           "value of 64.\n", ioc->name, max_sectors);
+               } else if (max_sectors > 8192) {
+                       shost->max_sectors = 8192;
+                       printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+                           "for max_sectors, range is 64 to 8192. Assigning "
+                           "default value of 8192.\n", ioc->name,
+                           max_sectors);
+               } else {
+                       shost->max_sectors = max_sectors & 0xFFFE;
+                       printk(MPT2SAS_INFO_FMT "The max_sectors value is "
+                           "set to %d\n", ioc->name, shost->max_sectors);
+               }
+       }
+
        if ((scsi_add_host(shost, &pdev->dev))) {
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
@@ -7505,7 +7666,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       u32 device_state;
+       pci_power_t device_state;
 
        mpt2sas_base_stop_watchdog(ioc);
        scsi_block_requests(shost);
@@ -7532,7 +7693,7 @@ _scsih_resume(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       u32 device_state = pdev->current_state;
+       pci_power_t device_state = pdev->current_state;
        int r;
 
        printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "