Print this page
XXXX Nexenta fixes for mpt_sas(7d)

@@ -65,11 +65,10 @@
  */
 #include <sys/note.h>
 #include <sys/scsi/scsi.h>
 #include <sys/pci.h>
 #include <sys/file.h>
-#include <sys/cpuvar.h>
 #include <sys/policy.h>
 #include <sys/sysevent.h>
 #include <sys/sysevent/eventdefs.h>
 #include <sys/sysevent/dr.h>
 #include <sys/sata/sata_defs.h>

@@ -93,11 +92,10 @@
  */
 #include <sys/scsi/impl/scsi_reset_notify.h>
 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
-
 #include <sys/raidioctl.h>
 
 #include <sys/fs/dv_node.h>     /* devfs_clean */
 
 /*

@@ -107,25 +105,10 @@
 #include <sys/fm/protocol.h>
 #include <sys/fm/util.h>
 #include <sys/fm/io/ddi.h>
 
 /*
- * For anyone who would modify the code in mptsas_driver, it must be awared
- * that from snv_145 where CR6910752(mpt_sas driver performance can be
- * improved) is integrated, the per_instance mutex m_mutex is not hold
- * in the key IO code path, including mptsas_scsi_start(), mptsas_intr()
- * and all of the recursive functions called in them, so don't
- * make it for granted that all operations are sync/exclude correctly. Before
- * doing any modification in key code path, and even other code path such as
- * DR, watchsubr, ioctl, passthrough etc, make sure the elements modified have
- * no releationship to elements shown in the fastpath
- * (function mptsas_handle_io_fastpath()) in ISR and its recursive functions.
- * otherwise, you have to use the new introduced mutex to protect them.
- * As to how to do correctly, refer to the comments in mptsas_intr().
- */
-
-/*
  * autoconfiguration data and routines.
  */
 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 static int mptsas_power(dev_info_t *dip, int component, int level);

@@ -214,10 +197,12 @@
 
 static void mptsas_ncmds_checkdrain(void *arg);
 
 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
+static int mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
+static void mptsas_accept_tx_waitq(mptsas_t *mpt);
 
 static int mptsas_do_detach(dev_info_t *dev);
 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
     struct scsi_pkt *pkt);

@@ -239,11 +224,10 @@
     uchar_t reason, uint_t stat);
 
 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
 static void mptsas_process_intr(mptsas_t *mpt,
     pMpi2ReplyDescriptorsUnion_t reply_desc_union);
-static int mptsas_handle_io_fastpath(mptsas_t *mpt, uint16_t SMID);
 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
     pMpi2ReplyDescriptorsUnion_t reply_desc);
 static void mptsas_handle_address_reply(mptsas_t *mpt,
     pMpi2ReplyDescriptorsUnion_t reply_desc);
 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);

@@ -251,10 +235,11 @@
     uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 
 static void mptsas_watch(void *arg);
 static void mptsas_watchsubr(mptsas_t *mpt);
 static void mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl);
+static void mptsas_kill_target(mptsas_t *mpt, mptsas_target_t *ptgt);
 
 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
     uint8_t *data, uint32_t request_size, uint32_t reply_size,
     uint32_t data_size, uint32_t direction, uint8_t *dataout,

@@ -306,32 +291,33 @@
     int *resid);
 
 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
 static void mptsas_free_active_slots(mptsas_t *mpt);
 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
-static int mptsas_start_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 
 static void mptsas_restart_hba(mptsas_t *mpt);
+static void mptsas_restart_waitq(mptsas_t *mpt);
 
 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
-static inline void mptsas_doneq_add0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
 
 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
 static void mptsas_doneq_empty(mptsas_t *mpt);
 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
 
 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
+static mptsas_cmd_t *mptsas_tx_waitq_rm(mptsas_t *mpt);
+static void mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 
+
 static void mptsas_start_watch_reset_delay();
 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
 static void mptsas_watch_reset_delay(void *arg);
 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 
-static int mptsas_outstanding_cmds_n(mptsas_t *mpt);
 /*
  * helper functions
  */
 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 

@@ -359,20 +345,13 @@
     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 
 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
     uint16_t *handle, mptsas_target_t **pptgt);
 static void mptsas_update_phymask(mptsas_t *mpt);
-static inline void mptsas_remove_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 
-static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
-    uint32_t *status, uint8_t cmd);
 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
     mptsas_phymask_t *phymask);
-static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
-    mptsas_phymask_t phymask);
-static int mptsas_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt,
-    uint32_t slotstatus);
 
 
 /*
  * Enumeration / DR functions
  */

@@ -429,11 +408,11 @@
 static void * mptsas_hash_search(mptsas_hash_table_t *hashtab, uint64_t key1,
     mptsas_phymask_t key2);
 static void * mptsas_hash_traverse(mptsas_hash_table_t *hashtab, int pos);
 
 mptsas_target_t *mptsas_tgt_alloc(mptsas_hash_table_t *, uint16_t, uint64_t,
-    uint32_t, mptsas_phymask_t, uint8_t, mptsas_t *);
+    uint32_t, mptsas_phymask_t, uint8_t);
 static mptsas_smp_t *mptsas_smp_alloc(mptsas_hash_table_t *hashtab,
     mptsas_smp_t *data);
 static void mptsas_smp_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
     mptsas_phymask_t phymask);
 static void mptsas_tgt_free(mptsas_hash_table_t *, uint64_t, mptsas_phymask_t);

@@ -479,10 +458,18 @@
 /*
  * Tunable timeout value for Inquiry VPD page 0x83
  * By default the value is 30 seconds.
  */
 int mptsas_inq83_retry_timeout = 30;
+/*
+ * Maximum number of command timeouts (0 - 255) considered acceptable.
+ */
+int mptsas_timeout_threshold = 2;
+/*
+ * Timeouts exceeding threshold within this period are considered excessive.
+ */
+int mptsas_timeout_interval = 30;
 
 /*
  * This is used to allocate memory for message frame storage, not for
  * data I/O DMA. All message frames must be stored in the first 4G of
  * physical memory.

@@ -1195,11 +1182,11 @@
 
         /* Initialize mutex used in interrupt handler */
         mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
             DDI_INTR_PRI(mpt->m_intr_pri));
         mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
-        mutex_init(&mpt->m_intr_mutex, NULL, MUTEX_DRIVER,
+        mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
             DDI_INTR_PRI(mpt->m_intr_pri));
         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
                 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
                     NULL, MUTEX_DRIVER,
                     DDI_INTR_PRI(mpt->m_intr_pri));

@@ -1298,10 +1285,12 @@
         /*
          * Initialize the wait and done FIFO queue
          */
         mpt->m_donetail = &mpt->m_doneq;
         mpt->m_waitqtail = &mpt->m_waitq;
+        mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
+        mpt->m_tx_draining = 0;
 
         /*
          * ioc cmd queue initialize
          */
         mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;

@@ -1457,11 +1446,11 @@
                 }
                 if (dr_taskq_create) {
                         ddi_taskq_destroy(mpt->m_dr_taskq);
                 }
                 if (mutex_init_done) {
-                        mutex_destroy(&mpt->m_intr_mutex);
+                        mutex_destroy(&mpt->m_tx_waitq_mutex);
                         mutex_destroy(&mpt->m_passthru_mutex);
                         mutex_destroy(&mpt->m_mutex);
                         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
                                 mutex_destroy(
                                     &mpt->m_phy_info[i].smhba_info.phy_mutex);

@@ -1875,11 +1864,11 @@
                             "!mptsas%d: Lower power request failed "
                             "during detach, ignoring.",
                             mpt->m_instance);
         }
 
-        mutex_destroy(&mpt->m_intr_mutex);
+        mutex_destroy(&mpt->m_tx_waitq_mutex);
         mutex_destroy(&mpt->m_passthru_mutex);
         mutex_destroy(&mpt->m_mutex);
         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
                 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
         }

@@ -2239,13 +2228,11 @@
                                     "mptsas_power: hard reset failed");
                                 mutex_exit(&mpt->m_mutex);
                                 return (DDI_FAILURE);
                         }
                 }
-                mutex_enter(&mpt->m_intr_mutex);
                 mpt->m_power_level = PM_LEVEL_D0;
-                mutex_exit(&mpt->m_intr_mutex);
                 break;
         case PM_LEVEL_D3:
                 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
                 MPTSAS_POWER_OFF(mpt);
                 break;

@@ -2632,17 +2619,14 @@
 }
 
 static void
 mptsas_alloc_reply_args(mptsas_t *mpt)
 {
-        if (mpt->m_replyh_args != NULL) {
-                kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
-                    * mpt->m_max_replies);
-                mpt->m_replyh_args = NULL;
-        }
+        if (mpt->m_replyh_args == NULL) {
         mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
             mpt->m_max_replies, KM_SLEEP);
+        }
 }
 
 static int
 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
 {

@@ -2997,46 +2981,166 @@
          * to the interrupt handler which is a pointer to your mptsas_t
          * structure; you'll have to remember which commands are outstanding
          * and which scsi_pkt is the currently-running command so the
          * interrupt handler can refer to the pkt to set completion
          * status, call the target driver back through pkt_comp, etc.
+         *
+         * If the instance lock is held by other thread, don't spin to wait
+         * for it. Instead, queue the cmd and next time when the instance lock
+         * is not held, accept all the queued cmd. A extra tx_waitq is
+         * introduced to protect the queue.
+         *
+         * The polled cmd will not be queud and accepted as usual.
+         *
+         * Under the tx_waitq mutex, record whether a thread is draining
+         * the tx_waitq.  An IO requesting thread that finds the instance
+         * mutex contended appends to the tx_waitq and while holding the
+         * tx_wait mutex, if the draining flag is not set, sets it and then
+         * proceeds to spin for the instance mutex. This scheme ensures that
+         * the last cmd in a burst be processed.
+         *
+         * we enable this feature only when the helper threads are enabled,
+         * at which we think the loads are heavy.
+         *
+         * per instance mutex m_tx_waitq_mutex is introduced to protect the
+         * m_tx_waitqtail, m_tx_waitq, m_tx_draining.
          */
 
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
+        if (mpt->m_doneq_thread_n) {
+                if (mutex_tryenter(&mpt->m_mutex) != 0) {
+                        rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
+                        mutex_exit(&mpt->m_mutex);
+                } else if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
+                        mutex_enter(&mpt->m_mutex);
+                        rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
+                        mutex_exit(&mpt->m_mutex);
+                } else {
+                        mutex_enter(&mpt->m_tx_waitq_mutex);
+                        /*
+                         * ptgt->m_dr_flag is protected by m_mutex or
+                         * m_tx_waitq_mutex. In this case, m_tx_waitq_mutex
+                         * is acquired.
+                         */
         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
                         /*
+                                         * The command should be allowed to
+                                         * retry by returning TRAN_BUSY to
+                                         * to stall the I/O's which come from
+                                         * scsi_vhci since the device/path is
+                                         * in unstable state now.
+                                         */
+                                        mutex_exit(&mpt->m_tx_waitq_mutex);
+                                        return (TRAN_BUSY);
+                                } else {
+                                        /*
+                                         * The device is offline, just fail the
+                                         * command by returning
+                                         * TRAN_FATAL_ERROR.
+                                         */
+                                        mutex_exit(&mpt->m_tx_waitq_mutex);
+                                        return (TRAN_FATAL_ERROR);
+                                }
+                        }
+                        if (mpt->m_tx_draining) {
+                                cmd->cmd_flags |= CFLAG_TXQ;
+                                *mpt->m_tx_waitqtail = cmd;
+                                mpt->m_tx_waitqtail = &cmd->cmd_linkp;
+                                mutex_exit(&mpt->m_tx_waitq_mutex);
+                        } else { /* drain the queue */
+                                mpt->m_tx_draining = 1;
+                                mutex_exit(&mpt->m_tx_waitq_mutex);
+                                mutex_enter(&mpt->m_mutex);
+                                rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
+                                mutex_exit(&mpt->m_mutex);
+                        }
+                }
+        } else {
+                mutex_enter(&mpt->m_mutex);
+                /*
+                 * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
+                 * in this case, m_mutex is acquired.
+                 */
+                if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
+                        if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
+                                /*
                          * commands should be allowed to retry by
                          * returning TRAN_BUSY to stall the I/O's
                          * which come from scsi_vhci since the device/
                          * path is in unstable state now.
                          */
-                        mutex_exit(&ptgt->m_tgt_intr_mutex);
+                                mutex_exit(&mpt->m_mutex);
                         return (TRAN_BUSY);
                 } else {
                         /*
                          * The device is offline, just fail the
                          * command by returning TRAN_FATAL_ERROR.
                          */
-                        mutex_exit(&ptgt->m_tgt_intr_mutex);
+                                mutex_exit(&mpt->m_mutex);
                         return (TRAN_FATAL_ERROR);
                 }
         }
-        mutex_exit(&ptgt->m_tgt_intr_mutex);
         rval = mptsas_accept_pkt(mpt, cmd);
+                mutex_exit(&mpt->m_mutex);
+        }
 
         return (rval);
 }
 
+/*
+ * Accept all the queued cmds(if any) before accept the current one.
+ */
 static int
+mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
+{
+        int rval;
+        mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
+
+        ASSERT(mutex_owned(&mpt->m_mutex));
+        /*
+         * The call to mptsas_accept_tx_waitq() must always be performed
+         * because that is where mpt->m_tx_draining is cleared.
+         */
+        mutex_enter(&mpt->m_tx_waitq_mutex);
+        mptsas_accept_tx_waitq(mpt);
+        mutex_exit(&mpt->m_tx_waitq_mutex);
+        /*
+         * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
+         * in this case, m_mutex is acquired.
+         */
+        if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
+                if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
+                        /*
+                         * The command should be allowed to retry by returning
+                         * TRAN_BUSY to stall the I/O's which come from
+                         * scsi_vhci since the device/path is in unstable state
+                         * now.
+                         */
+                        return (TRAN_BUSY);
+                } else {
+                        /*
+                         * The device is offline, just fail the command by
+                         * return TRAN_FATAL_ERROR.
+                         */
+                        return (TRAN_FATAL_ERROR);
+                }
+        }
+        rval = mptsas_accept_pkt(mpt, cmd);
+
+        return (rval);
+}
+
+static int
 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
 {
         int             rval = TRAN_ACCEPT;
         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
 
         NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
 
+        ASSERT(mutex_owned(&mpt->m_mutex));
+
         if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
                 rval = mptsas_prepare_pkt(cmd);
                 if (rval != TRAN_ACCEPT) {
                         cmd->cmd_flags &= ~CFLAG_TRANFLAG;
                         return (rval);

@@ -3044,88 +3148,75 @@
         }
 
         /*
          * reset the throttle if we were draining
          */
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
         if ((ptgt->m_t_ncmds == 0) &&
             (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
                 NDBG23(("reset throttle"));
                 ASSERT(ptgt->m_reset_delay == 0);
                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
         }
 
         /*
-         * If device handle has already been invalidated, just
-         * fail the command. In theory, command from scsi_vhci
-         * client is impossible send down command with invalid
-         * devhdl since devhdl is set after path offline, target
-         * driver is not suppose to select a offlined path.
+         * If HBA is being reset, the DevHandles are being re-initialized,
+         * which means that they could be invalid even if the target is still
+         * attached.  Check if being reset and if DevHandle is being
+         * re-initialized.  If this is the case, return BUSY so the I/O can be
+         * retried later.
          */
-        if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
-                NDBG20(("rejecting command, it might because invalid devhdl "
-                    "request."));
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
-                mutex_enter(&mpt->m_mutex);
-                /*
-                 * If HBA is being reset, the DevHandles are being
-                 * re-initialized, which means that they could be invalid
-                 * even if the target is still attached. Check if being reset
-                 * and if DevHandle is being re-initialized. If this is the
-                 * case, return BUSY so the I/O can be retried later.
-                 */
-                if (mpt->m_in_reset) {
-                        mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
-                            STAT_BUS_RESET);
+        if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) {
+                mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
                         if (cmd->cmd_flags & CFLAG_TXQ) {
                                 mptsas_doneq_add(mpt, cmd);
                                 mptsas_doneq_empty(mpt);
-                                mutex_exit(&mpt->m_mutex);
                                 return (rval);
                         } else {
-                                mutex_exit(&mpt->m_mutex);
                                 return (TRAN_BUSY);
                         }
                 }
+
+        /*
+         * If device handle has already been invalidated, just
+         * fail the command. In theory, command from scsi_vhci
+         * client is impossible send down command with invalid
+         * devhdl since devhdl is set after path offline, target
+         * driver is not suppose to select a offlined path.
+         */
+        if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
+                NDBG20(("rejecting command, it might because invalid devhdl "
+                    "request."));
                 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
                 if (cmd->cmd_flags & CFLAG_TXQ) {
                         mptsas_doneq_add(mpt, cmd);
                         mptsas_doneq_empty(mpt);
-                        mutex_exit(&mpt->m_mutex);
                         return (rval);
                 } else {
-                        mutex_exit(&mpt->m_mutex);
                         return (TRAN_FATAL_ERROR);
                 }
         }
-        mutex_exit(&ptgt->m_tgt_intr_mutex);
         /*
          * The first case is the normal case.  mpt gets a command from the
          * target driver and starts it.
          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
          * commands is m_max_requests - 2.
          */
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
-        if ((ptgt->m_t_throttle > HOLD_THROTTLE) &&
+        if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
+            (ptgt->m_t_throttle > HOLD_THROTTLE) &&
             (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
             (ptgt->m_reset_delay == 0) &&
             (ptgt->m_t_nwait == 0) &&
             ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
-                        (void) mptsas_start_cmd0(mpt, cmd);
+                        (void) mptsas_start_cmd(mpt, cmd);
                 } else {
-                        mutex_enter(&mpt->m_mutex);
                         mptsas_waitq_add(mpt, cmd);
-                        mutex_exit(&mpt->m_mutex);
                 }
         } else {
                 /*
                  * Add this pkt to the work queue
                  */
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
-                mutex_enter(&mpt->m_mutex);
                 mptsas_waitq_add(mpt, cmd);
 
                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
 

@@ -3136,11 +3227,10 @@
                          */
                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
                                 mptsas_doneq_empty(mpt);
                         }
                 }
-                mutex_exit(&mpt->m_mutex);
         }
         return (rval);
 }
 
 int

@@ -3147,102 +3237,49 @@
 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
 {
         mptsas_slots_t  *slots;
         int             slot;
         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
-        mptsas_slot_free_e_t    *pe;
-        int             qn, qn_first;
 
+        ASSERT(mutex_owned(&mpt->m_mutex));
         slots = mpt->m_active;
 
         /*
          * Account for reserved TM request slot and reserved SMID of 0.
          */
         ASSERT(slots->m_n_slots == (mpt->m_max_requests - 2));
 
-        qn = qn_first = CPU->cpu_seqid & (mpt->m_slot_freeq_pair_n - 1);
-
-qpair_retry:
-        ASSERT(qn < mpt->m_slot_freeq_pair_n);
-        mutex_enter(&mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_mutex);
-        pe = list_head(&mpt->m_slot_freeq_pairp[qn].m_slot_allocq.
-            s.m_fq_list);
-        if (!pe) { /* switch the allocq and releq */
-                mutex_enter(&mpt->m_slot_freeq_pairp[qn].m_slot_releq.
-                    s.m_fq_mutex);
-                if (mpt->m_slot_freeq_pairp[qn].m_slot_releq.s.m_fq_n) {
-                        mpt->m_slot_freeq_pairp[qn].
-                            m_slot_allocq.s.m_fq_n =
-                            mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_n;
-                        mpt->m_slot_freeq_pairp[qn].
-                            m_slot_allocq.s.m_fq_list.list_head.list_next =
-                            mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_list.list_head.list_next;
-                        mpt->m_slot_freeq_pairp[qn].
-                            m_slot_allocq.s.m_fq_list.list_head.list_prev =
-                            mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_list.list_head.list_prev;
-                        mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_list.list_head.list_prev->
-                            list_next =
-                            &mpt->m_slot_freeq_pairp[qn].
-                            m_slot_allocq.s.m_fq_list.list_head;
-                        mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_list.list_head.list_next->
-                            list_prev =
-                            &mpt->m_slot_freeq_pairp[qn].
-                            m_slot_allocq.s.m_fq_list.list_head;
-
-                        mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_list.list_head.list_next =
-                            mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_list.list_head.list_prev =
-                            &mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_list.list_head;
-                        mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_n = 0;
-                } else {
-                        mutex_exit(&mpt->m_slot_freeq_pairp[qn].
-                            m_slot_releq.s.m_fq_mutex);
-                        mutex_exit(&mpt->m_slot_freeq_pairp[qn].
-                            m_slot_allocq.s.m_fq_mutex);
-                        qn = (qn + 1) & (mpt->m_slot_freeq_pair_n - 1);
-                        if (qn == qn_first)
-                                return (FALSE);
-                        else
-                                goto qpair_retry;
+        /*
+         * m_tags is equivalent to the SMID when sending requests.  Since the
+         * SMID cannot be 0, start out at one if rolling over past the size
+         * of the request queue depth.  Also, don't use the last SMID, which is
+         * reserved for TM requests.
+         */
+        slot = (slots->m_tags)++;
+        if (slots->m_tags > slots->m_n_slots) {
+                slots->m_tags = 1;
                 }
-                mutex_exit(&mpt->m_slot_freeq_pairp[qn].
-                    m_slot_releq.s.m_fq_mutex);
-                pe = list_head(&mpt->m_slot_freeq_pairp[qn].
-                    m_slot_allocq.s.m_fq_list);
-                ASSERT(pe);
-        }
-        list_remove(&mpt->m_slot_freeq_pairp[qn].
-            m_slot_allocq.s.m_fq_list, pe);
-        slot = pe->slot;
+
+alloc_tag:
+        /* Validate tag, should never fail. */
+        if (slots->m_slot[slot] == NULL) {
         /*
          * Make sure SMID is not using reserved value of 0
          * and the TM request slot.
          */
-        ASSERT((slot > 0) && (slot <= slots->m_n_slots) &&
-            mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_n > 0);
+                ASSERT((slot > 0) && (slot <= slots->m_n_slots));
         cmd->cmd_slot = slot;
-        mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_n--;
-        ASSERT(mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_n >= 0);
+                slots->m_slot[slot] = cmd;
+                mpt->m_ncmds++;
 
-        mutex_exit(&mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_mutex);
         /*
          * only increment per target ncmds if this is not a
          * command that has no target associated with it (i.e. a
          * event acknoledgment)
          */
         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 ptgt->m_t_ncmds++;
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
         }
         cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
 
         /*
          * If initial timout is less than or equal to one tick, bump

@@ -3251,10 +3288,29 @@
          */
         if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
                 cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
         }
         return (TRUE);
+        } else {
+                int i;
+
+                /*
+                 * If slot in use, scan until a free one is found. Don't use 0
+                 * or final slot, which is reserved for TM requests.
+                 */
+                for (i = 0; i < slots->m_n_slots; i++) {
+                        slot = slots->m_tags;
+                        if (++(slots->m_tags) > slots->m_n_slots) {
+                                slots->m_tags = 1;
+                        }
+                        if (slots->m_slot[slot] == NULL) {
+                                NDBG22(("found free slot %d", slot));
+                                goto alloc_tag;
+                        }
+                }
+        }
+        return (FALSE);
 }
 
 /*
  * prepare the pkt:
  * the pkt may have been resubmitted or just reused so

@@ -3318,13 +3374,11 @@
     int (*callback)(), caddr_t arg)
 {
         mptsas_cmd_t            *cmd, *new_cmd;
         mptsas_t                *mpt = ADDR2MPT(ap);
         int                     failure = 1;
-#ifndef __sparc
         uint_t                  oldcookiec;
-#endif  /* __sparc */
         mptsas_target_t         *ptgt = NULL;
         int                     rval;
         mptsas_tgt_private_t    *tgt_private;
         int                     kf;
 

@@ -3358,32 +3412,24 @@
         if (pkt == NULL) {
                 ddi_dma_handle_t        save_dma_handle;
                 ddi_dma_handle_t        save_arq_dma_handle;
                 struct buf              *save_arq_bp;
                 ddi_dma_cookie_t        save_arqcookie;
-#ifdef  __sparc
-                mptti_t                 *save_sg;
-#endif  /* __sparc */
 
                 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
 
                 if (cmd) {
                         save_dma_handle = cmd->cmd_dmahandle;
                         save_arq_dma_handle = cmd->cmd_arqhandle;
                         save_arq_bp = cmd->cmd_arq_buf;
                         save_arqcookie = cmd->cmd_arqcookie;
-#ifdef  __sparc
-                        save_sg = cmd->cmd_sg;
-#endif  /* __sparc */
                         bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
                         cmd->cmd_dmahandle = save_dma_handle;
                         cmd->cmd_arqhandle = save_arq_dma_handle;
                         cmd->cmd_arq_buf = save_arq_bp;
                         cmd->cmd_arqcookie = save_arqcookie;
-#ifdef  __sparc
-                        cmd->cmd_sg = save_sg;
-#endif  /* __sparc */
+
                         pkt = (void *)((uchar_t *)cmd +
                             sizeof (struct mptsas_cmd));
                         pkt->pkt_ha_private = (opaque_t)cmd;
                         pkt->pkt_address = *ap;
                         pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;

@@ -3422,15 +3468,13 @@
                 cmd = PKT2CMD(pkt);
                 new_cmd = NULL;
         }
 
 
-#ifndef __sparc
         /* grab cmd->cmd_cookiec here as oldcookiec */
 
         oldcookiec = cmd->cmd_cookiec;
-#endif  /* __sparc */
 
         /*
          * If the dma was broken up into PARTIAL transfers cmd_nwin will be
          * greater than 0 and we'll need to grab the next dma window
          */

@@ -3576,11 +3620,11 @@
                  * array inside mptsas_cmd_t.
                  *
                  * We check cmd->cmd_cookiec against oldcookiec so
                  * the scatter-gather list is correctly allocated
                  */
-#ifndef __sparc
+
                 if (oldcookiec != cmd->cmd_cookiec) {
                         if (cmd->cmd_sg != (mptti_t *)NULL) {
                                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
                                     oldcookiec);
                                 cmd->cmd_sg = NULL;

@@ -3605,11 +3649,11 @@
                                         mptsas_scsi_destroy_pkt(ap, pkt);
                                 }
                                 return ((struct scsi_pkt *)NULL);
                         }
                 }
-#endif  /* __sparc */
+
                 dmap = cmd->cmd_sg;
 
                 ASSERT(cmd->cmd_cookie.dmac_size != 0);
 
                 /*

@@ -3685,16 +3729,16 @@
 
         if (cmd->cmd_flags & CFLAG_DMAVALID) {
                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
         }
-#ifndef __sparc
+
         if (cmd->cmd_sg) {
                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
                 cmd->cmd_sg = NULL;
         }
-#endif  /* __sparc */
+
         mptsas_free_extra_sgl_frame(mpt, cmd);
 
         if ((cmd->cmd_flags &
             (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
             CFLAG_SCBEXTERN)) == 0) {

@@ -3768,20 +3812,10 @@
                 cmd->cmd_dmahandle = NULL;
                 cmd->cmd_arqhandle = NULL;
                 cmd->cmd_arq_buf = NULL;
                 return (-1);
         }
-        /*
-         * In sparc, the sgl length in most of the cases would be 1, so we
-         * pre-allocate it in cache. On x86, the max number would be 256,
-         * pre-allocate a maximum would waste a lot of memory especially
-         * when many cmds are put onto waitq.
-         */
-#ifdef  __sparc
-        cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
-            MPTSAS_MAX_CMD_SEGS), KM_SLEEP);
-#endif  /* __sparc */
 
         return (0);
 }
 
 static void

@@ -3805,16 +3839,10 @@
         }
         if (cmd->cmd_dmahandle) {
                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
                 cmd->cmd_dmahandle = NULL;
         }
-#ifdef  __sparc
-        if (cmd->cmd_sg) {
-                kmem_free(cmd->cmd_sg, sizeof (mptti_t)* MPTSAS_MAX_CMD_SEGS);
-                cmd->cmd_sg = NULL;
-        }
-#endif  /* __sparc */
 }
 
 static int
 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
 {

@@ -4472,28 +4500,10 @@
 {
         int     rval = TRUE;
 
         NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
 
-        /*
-         * In order to avoid using m_mutex in ISR(a new separate mutex
-         * m_intr_mutex is introduced) and keep the same lock logic,
-         * the m_intr_mutex should be used to protect the getting and
-         * setting of the ReplyDescriptorIndex.
-         *
-         * Since the m_intr_mutex would be released during processing the poll
-         * cmd, so we should set the poll flag earlier here to make sure the
-         * polled cmd be handled in this thread/context. A side effect is other
-         * cmds during the period between the flag set and reset are also
-         * handled in this thread and not the ISR. Since the poll cmd is not
-         * so common, so the performance degradation in this case is not a big
-         * issue.
-         */
-        mutex_enter(&mpt->m_intr_mutex);
-        mpt->m_polled_intr = 1;
-        mutex_exit(&mpt->m_intr_mutex);
-
         if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
                 mptsas_restart_hba(mpt);
         }
 
         /*

@@ -4516,14 +4526,10 @@
                         rval = FALSE;
                         break;
                 }
         }
 
-        mutex_enter(&mpt->m_intr_mutex);
-        mpt->m_polled_intr = 0;
-        mutex_exit(&mpt->m_intr_mutex);
-
         if (rval == FALSE) {
 
                 /*
                  * this isn't supposed to happen, the hba must be wedged
                  * Mark this cmd as a timeout.

@@ -4556,16 +4562,15 @@
 static int
 mptsas_wait_intr(mptsas_t *mpt, int polltime)
 {
         int                             cnt;
         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
-        Mpi2ReplyDescriptorsUnion_t     reply_desc_union_v;
         uint32_t                        int_mask;
-        uint8_t reply_type;
 
         NDBG5(("mptsas_wait_intr"));
 
+        mpt->m_polled_intr = 1;
 
         /*
          * Get the current interrupt mask and disable interrupts.  When
          * re-enabling ints, set mask to saved value.
          */

@@ -4574,11 +4579,10 @@
 
         /*
          * Keep polling for at least (polltime * 1000) seconds
          */
         for (cnt = 0; cnt < polltime; cnt++) {
-                mutex_enter(&mpt->m_intr_mutex);
                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
                     DDI_DMA_SYNC_FORCPU);
 
                 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
                     MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);

@@ -4585,41 +4589,19 @@
 
                 if (ddi_get32(mpt->m_acc_post_queue_hdl,
                     &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
                     ddi_get32(mpt->m_acc_post_queue_hdl,
                     &reply_desc_union->Words.High) == 0xFFFFFFFF) {
-                        mutex_exit(&mpt->m_intr_mutex);
                         drv_usecwait(1000);
                         continue;
                 }
 
-                reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
-                    &reply_desc_union->Default.ReplyFlags);
-                reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
-                reply_desc_union_v.Default.ReplyFlags = reply_type;
-                if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
-                        reply_desc_union_v.SCSIIOSuccess.SMID =
-                            ddi_get16(mpt->m_acc_post_queue_hdl,
-                            &reply_desc_union->SCSIIOSuccess.SMID);
-                } else if (reply_type ==
-                    MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
-                        reply_desc_union_v.AddressReply.ReplyFrameAddress =
-                            ddi_get32(mpt->m_acc_post_queue_hdl,
-                            &reply_desc_union->AddressReply.ReplyFrameAddress);
-                        reply_desc_union_v.AddressReply.SMID =
-                            ddi_get16(mpt->m_acc_post_queue_hdl,
-                            &reply_desc_union->AddressReply.SMID);
-                }
                 /*
-                 * Clear the reply descriptor for re-use and increment
-                 * index.
+                 * The reply is valid, process it according to its
+                 * type.
                  */
-                ddi_put64(mpt->m_acc_post_queue_hdl,
-                    &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
-                    0xFFFFFFFFFFFFFFFF);
-                (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
-                    DDI_DMA_SYNC_FORDEV);
+                mptsas_process_intr(mpt, reply_desc_union);
 
                 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
                         mpt->m_post_index = 0;
                 }
 

@@ -4626,20 +4608,13 @@
                 /*
                  * Update the global reply index
                  */
                 ddi_put32(mpt->m_datap,
                     &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
-                mutex_exit(&mpt->m_intr_mutex);
+                mpt->m_polled_intr = 0;
 
                 /*
-                 * The reply is valid, process it according to its
-                 * type.
-                 */
-                mptsas_process_intr(mpt, &reply_desc_union_v);
-
-
-                /*
                  * Re-enable interrupts and quit.
                  */
                 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
                     int_mask);
                 return (TRUE);

@@ -4647,125 +4622,15 @@
         }
 
         /*
          * Clear polling flag, re-enable interrupts and quit.
          */
+        mpt->m_polled_intr = 0;
         ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
         return (FALSE);
 }
 
-/*
- * For fastpath, the m_intr_mutex should be held from the begining to the end,
- * so we only treat those cmds that need not release m_intr_mutex(even just for
- * a moment) as candidate for fast processing. otherwise, we don't handle them
- * and just return, then in ISR, those cmds would be handled later with m_mutex
- * held and m_intr_mutex not held.
- */
-static int
-mptsas_handle_io_fastpath(mptsas_t *mpt,
-    uint16_t SMID)
-{
-        mptsas_slots_t                          *slots = mpt->m_active;
-        mptsas_cmd_t                            *cmd = NULL;
-        struct scsi_pkt                         *pkt;
-
-        /*
-         * This is a success reply so just complete the IO.  First, do a sanity
-         * check on the SMID.  The final slot is used for TM requests, which
-         * would not come into this reply handler.
-         */
-        if ((SMID == 0) || (SMID > slots->m_n_slots)) {
-                mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
-                    SMID);
-                ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
-                return (TRUE);
-        }
-
-        cmd = slots->m_slot[SMID];
-
-        /*
-         * print warning and return if the slot is empty
-         */
-        if (cmd == NULL) {
-                mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
-                    "in slot %d", SMID);
-                return (TRUE);
-        }
-
-        pkt = CMD2PKT(cmd);
-        pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
-            STATE_GOT_STATUS);
-        if (cmd->cmd_flags & CFLAG_DMAVALID) {
-                pkt->pkt_state |= STATE_XFERRED_DATA;
-        }
-        pkt->pkt_resid = 0;
-
-        /*
-         * If the cmd is a IOC, or a passthrough, then we don't process it in
-         * fastpath, and later it would be handled by mptsas_process_intr()
-         * with m_mutex protected.
-         */
-        if (cmd->cmd_flags & (CFLAG_PASSTHRU | CFLAG_CMDIOC)) {
-                return (FALSE);
-        } else {
-                mptsas_remove_cmd0(mpt, cmd);
-        }
-
-        if (cmd->cmd_flags & CFLAG_RETRY) {
-                /*
-                 * The target returned QFULL or busy, do not add tihs
-                 * pkt to the doneq since the hba will retry
-                 * this cmd.
-                 *
-                 * The pkt has already been resubmitted in
-                 * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
-                 * Remove this cmd_flag here.
-                 */
-                cmd->cmd_flags &= ~CFLAG_RETRY;
-        } else {
-                mptsas_doneq_add0(mpt, cmd);
-        }
-
-        /*
-         * In fastpath, the cmd should only be a context reply, so just check
-         * the post queue of the reply descriptor and the dmahandle of the cmd
-         * is enough. No sense data in this case and no need to check the dma
-         * handle where sense data dma info is saved, the dma handle of the
-         * reply frame, and the dma handle of the reply free queue.
-         * For the dma handle of the request queue. Check fma here since we
-         * are sure the request must have already been sent/DMAed correctly.
-         * otherwise checking in mptsas_scsi_start() is not correct since
-         * at that time the dma may not start.
-         */
-        if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
-            DDI_SUCCESS) ||
-            (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
-            DDI_SUCCESS)) {
-                ddi_fm_service_impact(mpt->m_dip,
-                    DDI_SERVICE_UNAFFECTED);
-                pkt->pkt_reason = CMD_TRAN_ERR;
-                pkt->pkt_statistics = 0;
-        }
-        if (cmd->cmd_dmahandle &&
-            (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
-                ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
-                pkt->pkt_reason = CMD_TRAN_ERR;
-                pkt->pkt_statistics = 0;
-        }
-        if ((cmd->cmd_extra_frames &&
-            ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
-            DDI_SUCCESS) ||
-            (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
-            DDI_SUCCESS)))) {
-                ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
-                pkt->pkt_reason = CMD_TRAN_ERR;
-                pkt->pkt_statistics = 0;
-        }
-
-        return (TRUE);
-}
-
 static void
 mptsas_handle_scsi_io_success(mptsas_t *mpt,
     pMpi2ReplyDescriptorsUnion_t reply_desc)
 {
         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;

@@ -4772,12 +4637,14 @@
         uint16_t                                SMID;
         mptsas_slots_t                          *slots = mpt->m_active;
         mptsas_cmd_t                            *cmd = NULL;
         struct scsi_pkt                         *pkt;
 
+        ASSERT(mutex_owned(&mpt->m_mutex));
+
         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
-        SMID = scsi_io_success->SMID;
+        SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
 
         /*
          * This is a success reply so just complete the IO.  First, do a sanity
          * check on the SMID.  The final slot is used for TM requests, which
          * would not come into this reply handler.

@@ -4848,13 +4715,14 @@
         int                             reply_frame_no;
 
         ASSERT(mutex_owned(&mpt->m_mutex));
 
         address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
+        reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
+            &address_reply->ReplyFrameAddress);
+        SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &address_reply->SMID);
 
-        reply_addr = address_reply->ReplyFrameAddress;
-        SMID = address_reply->SMID;
         /*
          * If reply frame is not in the proper range we should ignore this
          * message and exit the interrupt handler.
          */
         if ((reply_addr < mpt->m_reply_frame_dma_addr) ||

@@ -4956,10 +4824,16 @@
                          * just let taskq resolve ack action
                          * and ack would be sent in taskq thread
                          */
                         NDBG20(("send mptsas_handle_event_sync success"));
                 }
+
+                if (mpt->m_in_reset) {
+                        NDBG20(("dropping event received during reset"));
+                        return;
+                }
+
                 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
                     (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
                         mptsas_log(mpt, CE_WARN, "No memory available"
                         "for dispatch taskq");
                         /*

@@ -5110,16 +4984,14 @@
         if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
             ((ioc_status & MPI2_IOCSTATUS_MASK) ==
             MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
                 pkt->pkt_reason = CMD_INCOMPLETE;
                 pkt->pkt_state |= STATE_GOT_BUS;
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 if (ptgt->m_reset_delay == 0) {
                         mptsas_set_throttle(mpt, ptgt,
                             DRAIN_THROTTLE);
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
                 return;
         }
 
         if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
                 responsedata &= 0x000000FF;

@@ -5215,15 +5087,13 @@
         case MPI2_SCSI_STATUS_GOOD:
                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
                         pkt->pkt_reason = CMD_DEV_GONE;
                         pkt->pkt_state |= STATE_GOT_BUS;
-                        mutex_enter(&ptgt->m_tgt_intr_mutex);
                         if (ptgt->m_reset_delay == 0) {
                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
                         }
-                        mutex_exit(&ptgt->m_tgt_intr_mutex);
                         NDBG31(("lost disk for target%d, command:%x",
                             Tgt(cmd), pkt->pkt_cdbp[0]));
                         break;
                 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
                         NDBG31(("data overrun: xferred=%d", xferred));

@@ -5266,13 +5136,11 @@
                          * set throttles to drain
                          */
                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
                         while (ptgt != NULL) {
-                                mutex_enter(&ptgt->m_tgt_intr_mutex);
                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
                         }
 

@@ -5280,13 +5148,11 @@
                          * retry command
                          */
                         cmd->cmd_flags |= CFLAG_RETRY;
                         cmd->cmd_pkt_flags |= FLAG_HEAD;
 
-                        mutex_exit(&mpt->m_mutex);
                         (void) mptsas_accept_pkt(mpt, cmd);
-                        mutex_enter(&mpt->m_mutex);
                         break;
                 default:
                         mptsas_log(mpt, CE_WARN,
                             "unknown ioc_status = %x\n", ioc_status);
                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "

@@ -5397,211 +5263,33 @@
         mpt->m_doneq_thread_n--;
         cv_broadcast(&mpt->m_doneq_thread_cv);
         mutex_exit(&mpt->m_doneq_mutex);
 }
 
+
 /*
  * mpt interrupt handler.
  */
 static uint_t
 mptsas_intr(caddr_t arg1, caddr_t arg2)
 {
         mptsas_t                        *mpt = (void *)arg1;
         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
         uchar_t                         did_reply = FALSE;
-        int                             i = 0, j;
-        uint8_t                         reply_type;
-        uint16_t                        SMID;
 
         NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
 
-        /*
-         * 1.
-         * To avoid using m_mutex in the ISR(ISR referes not only mptsas_intr,
-         * but all of the recursive called functions in it. the same below),
-         * separate mutexs are introduced to protect the elements shown in ISR.
-         * 3 type of mutex are involved here:
-         *      a)per instance mutex m_intr_mutex.
-         *      b)per target mutex m_tgt_intr_mutex.
-         *      c)mutex that protect the free slot.
-         *
-         * a)per instance mutex m_intr_mutex:
-         * used to protect m_options, m_power, m_waitq, etc that would be
-         * checked/modified in ISR; protect the getting and setting the reply
-         * descriptor index; protect the m_slots[];
-         *
-         * b)per target mutex m_tgt_intr_mutex:
-         * used to protect per target element which has relationship to ISR.
-         * contention for the new per target mutex is just as high as it in
-         * sd(7d) driver.
-         *
-         * c)mutexs that protect the free slots:
-         * those mutexs are introduced to minimize the mutex contentions
-         * between the IO request threads where free slots are allocated
-         * for sending cmds and ISR where slots holding outstanding cmds
-         * are returned to the free pool.
-         * the idea is like this:
-         * 1) Partition all of the free slot into NCPU groups. For example,
-         * In system where we have 15 slots, and 4 CPU, then slot s1,s5,s9,s13
-         * are marked belonging to CPU1, s2,s6,s10,s14 to CPU2, s3,s7,s11,s15
-         * to CPU3, and s4,s8,s12 to CPU4.
-         * 2) In each of the group, an alloc/release queue pair is created,
-         * and both the allocq and the releaseq have a dedicated mutex.
-         * 3) When init, all of the slots in a CPU group are inserted into the
-         * allocq of its CPU's pair.
-         * 4) When doing IO,
-         * mptsas_scsi_start()
-         * {
-         *      cpuid = the cpu NO of the cpu where this thread is running on
-         * retry:
-         *      mutex_enter(&allocq[cpuid]);
-         *      if (get free slot = success) {
-         *              remove the slot from the allocq
-         *              mutex_exit(&allocq[cpuid]);
-         *              return(success);
-         *      } else { // exchange allocq and releaseq and try again
-         *              mutex_enter(&releq[cpuid]);
-         *              exchange the allocq and releaseq of this pair;
-         *              mutex_exit(&releq[cpuid]);
-         *              if (try to get free slot again = success) {
-         *                      remove the slot from the allocq
-         *                      mutex_exit(&allocq[cpuid]);
-         *                      return(success);
-         *              } else {
-         *                      MOD(cpuid)++;
-         *                      goto retry;
-         *                      if (all CPU groups tried)
-         *                              mutex_exit(&allocq[cpuid]);
-         *                              return(failure);
-         *              }
-         *      }
-         * }
-         * ISR()
-         * {
-         *              cpuid = the CPU group id where the slot sending the
-         *              cmd belongs;
-         *              mutex_enter(&releq[cpuid]);
-         *              remove the slot from the releaseq
-         *              mutex_exit(&releq[cpuid]);
-         * }
-         * This way, only when the queue pair doing exchange have mutex
-         * contentions.
-         *
-         * For mutex m_intr_mutex and m_tgt_intr_mutex, there are 2 scenarios:
-         *
-         * a)If the elements are only checked but not modified in the ISR, then
-         * only the places where those elements are modifed(outside of ISR)
-         * need to be protected by the new introduced mutex.
-         * For example, data A is only read/checked in ISR, then we need do
-         * like this:
-         * In ISR:
-         * {
-         *      mutex_enter(&new_mutex);
-         *      read(A);
-         *      mutex_exit(&new_mutex);
-         *      //the new_mutex here is either the m_tgt_intr_mutex or
-         *      //the m_intr_mutex.
-         * }
-         * In non-ISR
-         * {
-         *      mutex_enter(&m_mutex); //the stock driver already did this
-         *      mutex_enter(&new_mutex);
-         *      write(A);
-         *      mutex_exit(&new_mutex);
-         *      mutex_exit(&m_mutex); //the stock driver already did this
-         *
-         *      read(A);
-         *      // read(A) in non-ISR is not required to be protected by new
-         *      // mutex since 'A' has already been protected by m_mutex
-         *      // outside of the ISR
-         * }
-         *
-         * Those fields in mptsas_target_t/ptgt which are only read in ISR
-         * fall into this catergory. So they, together with the fields which
-         * are never read in ISR, are not necessary to be protected by
-         * m_tgt_intr_mutex, don't bother.
-         * checking of m_waitq also falls into this catergory. so all of the
-         * place outside of ISR where the m_waitq is modified, such as in
-         * mptsas_waitq_add(), mptsas_waitq_delete(), mptsas_waitq_rm(),
-         * m_intr_mutex should be used.
-         *
-         * b)If the elements are modified in the ISR, then each place where
-         * those elements are referred(outside of ISR) need to be protected
-         * by the new introduced mutex. Of course, if those elements only
-         * appear in the non-key code path, that is, they don't affect
-         * performance, then the m_mutex can still be used as before.
-         * For example, data B is modified in key code path in ISR, and data C
-         * is modified in non-key code path in ISR, then we can do like this:
-         * In ISR:
-         * {
-         *      mutex_enter(&new_mutex);
-         *      wirte(B);
-         *      mutex_exit(&new_mutex);
-         *      if (seldom happen) {
-         *              mutex_enter(&m_mutex);
-         *              write(C);
-         *              mutex_exit(&m_mutex);
-         *      }
-         *      //the new_mutex here is either the m_tgt_intr_mutex or
-         *      //the m_intr_mutex.
-         * }
-         * In non-ISR
-         * {
-         *      mutex_enter(&new_mutex);
-         *      write(B);
-         *      mutex_exit(&new_mutex);
-         *
-         *      mutex_enter(&new_mutex);
-         *      read(B);
-         *      mutex_exit(&new_mutex);
-         *      // both write(B) and read(B) in non-ISR is required to be
-         *      // protected by new mutex outside of the ISR
-         *
-         *      mutex_enter(&m_mutex); //the stock driver already did this
-         *      read(C);
-         *      write(C);
-         *      mutex_exit(&m_mutex); //the stock driver already did this
-         *      // both write(C) and read(C) in non-ISR have been already
-         *      // been protected by m_mutex outside of the ISR
-         * }
-         *
-         * For example, ptgt->m_t_ncmds fall into 'B' of this catergory, and
-         * elements shown in address reply, restart_hba, passthrough, IOC
-         * fall into 'C' of  this catergory.
-         *
-         * In any case where mutexs are nested, make sure in the following
-         * order:
-         *      m_mutex -> m_intr_mutex -> m_tgt_intr_mutex
-         *      m_intr_mutex -> m_tgt_intr_mutex
-         *      m_mutex -> m_intr_mutex
-         *      m_mutex -> m_tgt_intr_mutex
-         *
-         * 2.
-         * Make sure at any time, getting the ReplyDescriptor by m_post_index
-         * and setting m_post_index to the ReplyDescriptorIndex register are
-         * atomic. Since m_mutex is not used for this purpose in ISR, the new
-         * mutex m_intr_mutex must play this role. So mptsas_poll(), where this
-         * kind of getting/setting is also performed, must use m_intr_mutex.
-         * Note, since context reply in ISR/process_intr is the only code path
-         * which affect performance, a fast path is introduced to only handle
-         * the read/write IO having context reply. For other IOs such as
-         * passthrough and IOC with context reply and all address reply, we
-         * use the as-is process_intr() to handle them. In order to keep the
-         * same semantics in process_intr(), make sure any new mutex is not held
-         * before enterring it.
-         */
+        mutex_enter(&mpt->m_mutex);
 
-        mutex_enter(&mpt->m_intr_mutex);
-
         /*
          * If interrupts are shared by two channels then check whether this
          * interrupt is genuinely for this channel by making sure first the
          * chip is in high power state.
          */
         if ((mpt->m_options & MPTSAS_OPT_PM) &&
             (mpt->m_power_level != PM_LEVEL_D0)) {
-                mutex_exit(&mpt->m_intr_mutex);
+                mutex_exit(&mpt->m_mutex);
                 return (DDI_INTR_UNCLAIMED);
         }
 
         /*
          * If polling, interrupt was triggered by some shared interrupt because

@@ -5608,11 +5296,11 @@
          * IOC interrupts are disabled during polling, so polling routine will
          * handle any replies.  Considering this, if polling is happening,
          * return with interrupt unclaimed.
          */
         if (mpt->m_polled_intr) {
-                mutex_exit(&mpt->m_intr_mutex);
+                mutex_exit(&mpt->m_mutex);
                 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
                 return (DDI_INTR_UNCLAIMED);
         }
 
         /*

@@ -5643,165 +5331,94 @@
                          * type.  Also, set a flag for updating the reply index
                          * after they've all been processed.
                          */
                         did_reply = TRUE;
 
-                        reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
-                            &reply_desc_union->Default.ReplyFlags);
-                        reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
-                        mpt->m_reply[i].Default.ReplyFlags = reply_type;
-                        if (reply_type ==
-                            MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
-                                SMID = ddi_get16(mpt->m_acc_post_queue_hdl,
-                                    &reply_desc_union->SCSIIOSuccess.SMID);
-                                if (mptsas_handle_io_fastpath(mpt, SMID) !=
-                                    TRUE) {
-                                        mpt->m_reply[i].SCSIIOSuccess.SMID =
-                                            SMID;
-                                        i++;
-                                }
-                        } else if (reply_type ==
-                            MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
-                                mpt->m_reply[i].AddressReply.ReplyFrameAddress =
-                                    ddi_get32(mpt->m_acc_post_queue_hdl,
-                                    &reply_desc_union->AddressReply.
-                                    ReplyFrameAddress);
-                                mpt->m_reply[i].AddressReply.SMID =
-                                    ddi_get16(mpt->m_acc_post_queue_hdl,
-                                    &reply_desc_union->AddressReply.SMID);
-                                i++;
-                        }
-                        /*
-                         * Clear the reply descriptor for re-use and increment
-                         * index.
-                         */
-                        ddi_put64(mpt->m_acc_post_queue_hdl,
-                            &((uint64_t *)(void *)mpt->m_post_queue)
-                            [mpt->m_post_index], 0xFFFFFFFFFFFFFFFF);
-                        (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
-                            DDI_DMA_SYNC_FORDEV);
+                        mptsas_process_intr(mpt, reply_desc_union);
 
                         /*
                          * Increment post index and roll over if needed.
                          */
                         if (++mpt->m_post_index == mpt->m_post_queue_depth) {
                                 mpt->m_post_index = 0;
                         }
-                        if (i >= MPI_ADDRESS_COALSCE_MAX)
-                                break;
                 }
 
                 /*
                  * Update the global reply index if at least one reply was
                  * processed.
                  */
                 if (did_reply) {
                         ddi_put32(mpt->m_datap,
                             &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
-
-                        /*
-                         * For fma, only check the PIO is required and enough
-                         * here. Those cases where fastpath is not hit, the
-                         * mptsas_fma_check() check all of the types of
-                         * fma. That is not necessary and sometimes not
-                         * correct. fma check should only be done after
-                         * the PIO and/or dma is performed.
-                         */
-                        if ((mptsas_check_acc_handle(mpt->m_datap) !=
-                            DDI_SUCCESS)) {
-                                ddi_fm_service_impact(mpt->m_dip,
-                                    DDI_SERVICE_UNAFFECTED);
                         }
-
-                }
         } else {
-                mutex_exit(&mpt->m_intr_mutex);
+                mutex_exit(&mpt->m_mutex);
                 return (DDI_INTR_UNCLAIMED);
         }
         NDBG1(("mptsas_intr complete"));
-        mutex_exit(&mpt->m_intr_mutex);
 
         /*
-         * Since most of the cmds(read and write IO with success return.)
-         * have already been processed in fast path in which the m_mutex
-         * is not held, handling here the address reply and other context reply
-         * such as passthrough and IOC cmd with m_mutex held should be a big
-         * issue for performance.
-         * If holding m_mutex to process these cmds was still an obvious issue,
-         * we can process them in a taskq.
-         */
-        for (j = 0; j < i; j++) {
-                mutex_enter(&mpt->m_mutex);
-                mptsas_process_intr(mpt, &mpt->m_reply[j]);
-                mutex_exit(&mpt->m_mutex);
-        }
-
-        /*
          * If no helper threads are created, process the doneq in ISR. If
          * helpers are created, use the doneq length as a metric to measure the
          * load on the interrupt CPU. If it is long enough, which indicates the
          * load is heavy, then we deliver the IO completions to the helpers.
          * This measurement has some limitations, although it is simple and
          * straightforward and works well for most of the cases at present.
          */
-        if (!mpt->m_doneq_thread_n) {
+        if (!mpt->m_doneq_thread_n ||
+            (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
                 mptsas_doneq_empty(mpt);
         } else {
-                int helper = 1;
-                mutex_enter(&mpt->m_intr_mutex);
-                if (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)
-                        helper = 0;
-                mutex_exit(&mpt->m_intr_mutex);
-                if (helper) {
                         mptsas_deliver_doneq_thread(mpt);
-                } else {
-                        mptsas_doneq_empty(mpt);
                 }
-        }
 
         /*
          * If there are queued cmd, start them now.
          */
-        mutex_enter(&mpt->m_intr_mutex);
         if (mpt->m_waitq != NULL) {
-                mutex_exit(&mpt->m_intr_mutex);
-                mutex_enter(&mpt->m_mutex);
-                mptsas_restart_hba(mpt);
+                mptsas_restart_waitq(mpt);
+        }
+
                 mutex_exit(&mpt->m_mutex);
                 return (DDI_INTR_CLAIMED);
-        }
-        mutex_exit(&mpt->m_intr_mutex);
-        return (DDI_INTR_CLAIMED);
 }
 
-/*
- * In ISR, the successfully completed read and write IO are processed in a
- * fast path. This function is only used to handle non-fastpath IO, including
- * all of the address reply, and the context reply for IOC cmd, passthrough,
- * etc.
- * This function is also used to process polled cmd.
- */
 static void
 mptsas_process_intr(mptsas_t *mpt,
     pMpi2ReplyDescriptorsUnion_t reply_desc_union)
 {
         uint8_t reply_type;
 
+        ASSERT(mutex_owned(&mpt->m_mutex));
+
         /*
          * The reply is valid, process it according to its
          * type.  Also, set a flag for updated the reply index
          * after they've all been processed.
          */
-        reply_type = reply_desc_union->Default.ReplyFlags;
+        reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
+            &reply_desc_union->Default.ReplyFlags);
+        reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
         if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
                 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
         } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
                 mptsas_handle_address_reply(mpt, reply_desc_union);
         } else {
                 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
         }
+
+        /*
+         * Clear the reply descriptor for re-use and increment
+         * index.
+         */
+        ddi_put64(mpt->m_acc_post_queue_hdl,
+            &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
+            0xFFFFFFFFFFFFFFFF);
+        (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
+            DDI_DMA_SYNC_FORDEV);
 }
 
 /*
  * handle qfull condition
  */

@@ -5819,37 +5436,30 @@
                  * qfull-retries capability to 0. In either case
                  * we want the target driver's QFULL handling
                  * to kick in. We do this by having pkt_reason
                  * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
                  */
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
         } else {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 if (ptgt->m_reset_delay == 0) {
                         ptgt->m_t_throttle =
                             max((ptgt->m_t_ncmds - 2), 0);
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 cmd->cmd_pkt_flags |= FLAG_HEAD;
                 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
                 cmd->cmd_flags |= CFLAG_RETRY;
 
-                mutex_exit(&mpt->m_mutex);
                 (void) mptsas_accept_pkt(mpt, cmd);
-                mutex_enter(&mpt->m_mutex);
 
                 /*
                  * when target gives queue full status with no commands
                  * outstanding (m_t_ncmds == 0), throttle is set to 0
                  * (HOLD_THROTTLE), and the queue full handling start
                  * (see psarc/1994/313); if there are commands outstanding,
                  * throttle is set to (m_t_ncmds - 2)
                  */
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
                         /*
                          * By setting throttle to QFULL_THROTTLE, we
                          * avoid submitting new commands and in
                          * mptsas_restart_cmd find out slots which need

@@ -5860,11 +5470,10 @@
                                 mpt->m_restart_cmd_timeid =
                                     timeout(mptsas_restart_cmd, mpt,
                                     ptgt->m_qfull_retry_interval);
                         }
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
         }
 }
 
 mptsas_phymask_t
 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)

@@ -6158,12 +5767,18 @@
                 }
                 ASSERT(parent);
 handle_topo_change:
 
                 mutex_enter(&mpt->m_mutex);
-
+                /*
+                 * If HBA is being reset, don't perform operations depending
+                 * on the IOC. We must free the topo list, however.
+                 */
+                if (!mpt->m_in_reset)
                 mptsas_handle_topo_change(topo_node, parent);
+                else
+                        NDBG20(("skipping topo change received during reset"));
                 save_node = topo_node;
                 topo_node = topo_node->next;
                 ASSERT(save_node);
                 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
                 mutex_exit(&mpt->m_mutex);

@@ -6449,14 +6064,10 @@
                                 break;
                         }
                 }
 
                 mutex_enter(&mpt->m_mutex);
-                if (mptsas_set_led_status(mpt, ptgt, 0) != DDI_SUCCESS) {
-                        NDBG14(("mptsas: clear LED for tgt %x failed",
-                            ptgt->m_slot_num));
-                }
                 if (rval == DDI_SUCCESS) {
                         mptsas_tgt_free(&mpt->m_active->m_tgttbl,
                             ptgt->m_sas_wwn, ptgt->m_phymask);
                         ptgt = NULL;
                 } else {

@@ -6463,15 +6074,15 @@
                         /*
                          * clean DR_INTRANSITION flag to allow I/O down to
                          * PHCI driver since failover finished.
                          * Invalidate the devhdl
                          */
-                        mutex_enter(&ptgt->m_tgt_intr_mutex);
                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
                         ptgt->m_tgt_unconfigured = 0;
+                        mutex_enter(&mpt->m_tx_waitq_mutex);
                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
-                        mutex_exit(&ptgt->m_tgt_intr_mutex);
+                        mutex_exit(&mpt->m_tx_waitq_mutex);
                 }
 
                 /*
                  * Send SAS IO Unit Control to free the dev handle
                  */

@@ -7013,18 +6624,19 @@
                                 }
 
                                 /*
                                  * Update DR flag immediately avoid I/O failure
                                  * before failover finish. Pay attention to the
-                                 * mutex protect, we need grab the per target
-                                 * mutex during set m_dr_flag because the
-                                 * m_mutex would not be held all the time in
-                                 * mptsas_scsi_start().
+                                 * mutex protect, we need grab m_tx_waitq_mutex
+                                 * during set m_dr_flag because we won't add
+                                 * the following command into waitq, instead,
+                                 * we need return TRAN_BUSY in the tran_start
+                                 * context.
                                  */
-                                mutex_enter(&ptgt->m_tgt_intr_mutex);
+                                mutex_enter(&mpt->m_tx_waitq_mutex);
                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
+                                mutex_exit(&mpt->m_tx_waitq_mutex);
 
                                 topo_node = kmem_zalloc(
                                     sizeof (mptsas_topo_change_list_t),
                                     KM_SLEEP);
                                 topo_node->mpt = mpt;

@@ -7253,13 +6865,13 @@
                                 (void) mptsas_delete_volume(mpt, volhandle);
 
                                 /*
                                  * Update DR flag immediately avoid I/O failure
                                  */
-                                mutex_enter(&ptgt->m_tgt_intr_mutex);
+                                mutex_enter(&mpt->m_tx_waitq_mutex);
                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
+                                mutex_exit(&mpt->m_tx_waitq_mutex);
 
                                 topo_node = kmem_zalloc(
                                     sizeof (mptsas_topo_change_list_t),
                                     KM_SLEEP);
                                 topo_node->mpt = mpt;

@@ -7287,13 +6899,13 @@
                                         break;
 
                                 /*
                                  * Update DR flag immediately avoid I/O failure
                                  */
-                                mutex_enter(&ptgt->m_tgt_intr_mutex);
+                                mutex_enter(&mpt->m_tx_waitq_mutex);
                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
+                                mutex_exit(&mpt->m_tx_waitq_mutex);
 
                                 topo_node = kmem_zalloc(
                                     sizeof (mptsas_topo_change_list_t),
                                     KM_SLEEP);
                                 topo_node->mpt = mpt;

@@ -7384,10 +6996,18 @@
         replyh_arg = (m_replyh_arg_t *)args;
         rfm = replyh_arg->rfm;
         mpt = replyh_arg->mpt;
 
         mutex_enter(&mpt->m_mutex);
+        /*
+         * If HBA is being reset, drop incoming event.
+         */
+        if (mpt->m_in_reset) {
+                NDBG20(("dropping event received prior to reset"));
+                mutex_exit(&mpt->m_mutex);
+                return;
+        }
 
         eventreply = (pMpi2EventNotificationReply_t)
             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
 

@@ -7944,60 +7564,31 @@
         mpt->m_restart_cmd_timeid = 0;
 
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 if (ptgt->m_reset_delay == 0) {
                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
                                 mptsas_set_throttle(mpt, ptgt,
                                     MAX_THROTTLE);
                         }
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
         mptsas_restart_hba(mpt);
         mutex_exit(&mpt->m_mutex);
 }
 
-/*
- * mptsas_remove_cmd0 is similar to mptsas_remove_cmd except that it is called
- * where m_intr_mutex has already been held.
- */
 void
 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
 {
-        ASSERT(mutex_owned(&mpt->m_mutex));
-
-        /*
-         * With new fine-grained lock mechanism, the outstanding cmd is only
-         * linked to m_active before the dma is triggerred(MPTSAS_START_CMD)
-         * to send it. that is, mptsas_save_cmd() doesn't link the outstanding
-         * cmd now. So when mptsas_remove_cmd is called, a mptsas_save_cmd must
-         * have been called, but the cmd may have not been linked.
-         * For mptsas_remove_cmd0, the cmd must have been linked.
-         * In order to keep the same semantic, we link the cmd to the
-         * outstanding cmd list.
-         */
-        mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
-
-        mutex_enter(&mpt->m_intr_mutex);
-        mptsas_remove_cmd0(mpt, cmd);
-        mutex_exit(&mpt->m_intr_mutex);
-}
-
-static inline void
-mptsas_remove_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd)
-{
         int             slot;
         mptsas_slots_t  *slots = mpt->m_active;
         int             t;
         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
-        mptsas_slot_free_e_t    *pe;
 
         ASSERT(cmd != NULL);
         ASSERT(cmd->cmd_queued == FALSE);
 
         /*

@@ -8008,56 +7599,41 @@
                 return;
         }
 
         t = Tgt(cmd);
         slot = cmd->cmd_slot;
-        pe = mpt->m_slot_free_ae + slot - 1;
-        ASSERT(cmd == slots->m_slot[slot]);
-        ASSERT((slot > 0) && slot < (mpt->m_max_requests - 1));
 
         /*
          * remove the cmd.
          */
-        mutex_enter(&mpt->m_slot_freeq_pairp[pe->cpuid].
-            m_slot_releq.s.m_fq_mutex);
-        NDBG31(("mptsas_remove_cmd0: removing cmd=0x%p", (void *)cmd));
+        if (cmd == slots->m_slot[slot]) {
+                NDBG31(("mptsas_remove_cmd: removing cmd=0x%p", (void *)cmd));
         slots->m_slot[slot] = NULL;
-        ASSERT(pe->slot == slot);
-        list_insert_tail(&mpt->m_slot_freeq_pairp[pe->cpuid].
-            m_slot_releq.s.m_fq_list, pe);
-        mpt->m_slot_freeq_pairp[pe->cpuid].m_slot_releq.s.m_fq_n++;
-        ASSERT(mpt->m_slot_freeq_pairp[pe->cpuid].
-            m_slot_releq.s.m_fq_n <= mpt->m_max_requests - 2);
-        mutex_exit(&mpt->m_slot_freeq_pairp[pe->cpuid].
-            m_slot_releq.s.m_fq_mutex);
+                mpt->m_ncmds--;
 
         /*
          * only decrement per target ncmds if command
          * has a target associated with it.
          */
         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 ptgt->m_t_ncmds--;
                 /*
                  * reset throttle if we just ran an untagged command
                  * to a tagged target
                  */
                 if ((ptgt->m_t_ncmds == 0) &&
                     ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
         }
 
+        }
+
         /*
          * This is all we need to do for ioc commands.
-         * The ioc cmds would never be handled in fastpath in ISR, so we make
-         * sure the mptsas_return_to_pool() would always be called with
-         * m_mutex protected.
          */
         if (cmd->cmd_flags & CFLAG_CMDIOC) {
-                ASSERT(mutex_owned(&mpt->m_mutex));
                 mptsas_return_to_pool(mpt, cmd);
                 return;
         }
 
         /*

@@ -8070,11 +7646,10 @@
          * If no duplicates, we have to scan through tag que and
          * find the longest timeout value and use it.  This is
          * going to take a while...
          * Add 1 to m_n_slots to account for TM request.
          */
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
         if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
                 if (--(ptgt->m_dups) == 0) {
                         if (ptgt->m_t_ncmds) {
                                 mptsas_cmd_t *ssp;
                                 uint_t n = 0;

@@ -8104,23 +7679,44 @@
                 }
         }
         ptgt->m_timeout = ptgt->m_timebase;
 
         ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
-        mutex_exit(&ptgt->m_tgt_intr_mutex);
 }
 
 /*
+ * accept all cmds on the tx_waitq if any and then
  * start a fresh request from the top of the device queue.
+ *
+ * since there are always cmds queued on the tx_waitq, and rare cmds on
+ * the instance waitq, so this function should not be invoked in the ISR,
+ * the mptsas_restart_waitq() is invoked in the ISR instead. otherwise, the
+ * burden belongs to the IO dispatch CPUs is moved the interrupt CPU.
  */
 static void
 mptsas_restart_hba(mptsas_t *mpt)
 {
+        ASSERT(mutex_owned(&mpt->m_mutex));
+
+        mutex_enter(&mpt->m_tx_waitq_mutex);
+        if (mpt->m_tx_waitq) {
+                mptsas_accept_tx_waitq(mpt);
+        }
+        mutex_exit(&mpt->m_tx_waitq_mutex);
+        mptsas_restart_waitq(mpt);
+}
+
+/*
+ * start a fresh request from the top of the device queue
+ */
+static void
+mptsas_restart_waitq(mptsas_t *mpt)
+{
         mptsas_cmd_t    *cmd, *next_cmd;
         mptsas_target_t *ptgt = NULL;
 
-        NDBG1(("mptsas_restart_hba: mpt=0x%p", (void *)mpt));
+        NDBG1(("mptsas_restart_waitq: mpt=0x%p", (void *)mpt));
 
         ASSERT(mutex_owned(&mpt->m_mutex));
 
         /*
          * If there is a reset delay, don't start any cmds.  Otherwise, start

@@ -8171,249 +7767,70 @@
                         cmd = next_cmd;
                         continue;
                 }
 
                 ptgt = cmd->cmd_tgt_addr;
-                if (ptgt) {
-                        mutex_enter(&mpt->m_intr_mutex);
-                        mutex_enter(&ptgt->m_tgt_intr_mutex);
-                        if ((ptgt->m_t_throttle == DRAIN_THROTTLE) &&
+                if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
                             (ptgt->m_t_ncmds == 0)) {
                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
                         }
-                        if ((ptgt->m_reset_delay == 0) &&
-                            (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
-                                mutex_exit(&mpt->m_intr_mutex);
+                if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
+                    (ptgt && (ptgt->m_reset_delay == 0)) &&
+                    (ptgt && (ptgt->m_t_ncmds <
+                    ptgt->m_t_throttle))) {
                                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
                                         mptsas_waitq_delete(mpt, cmd);
                                         (void) mptsas_start_cmd(mpt, cmd);
                                 }
-                                goto out;
                         }
-                        mutex_exit(&ptgt->m_tgt_intr_mutex);
-                        mutex_exit(&mpt->m_intr_mutex);
-                }
-out:
                 cmd = next_cmd;
         }
 }
-
 /*
- * mpt tag type lookup
+ * Cmds are queued if tran_start() doesn't get the m_mutexlock(no wait).
+ * Accept all those queued cmds before new cmd is accept so that the
+ * cmds are sent in order.
  */
-static char mptsas_tag_lookup[] =
-        {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
-
-/*
- * mptsas_start_cmd0 is similar to mptsas_start_cmd, except that, it is called
- * without ANY mutex protected, while, mptsas_start_cmd is called with m_mutex
- * protected.
- *
- * the relevant field in ptgt should be protected by m_tgt_intr_mutex in both
- * functions.
- *
- * before the cmds are linked on the slot for monitor as outstanding cmds, they
- * are accessed as slab objects, so slab framework ensures the exclusive access,
- * and no other mutex is requireed. Linking for monitor and the trigger of dma
- * must be done exclusively.
- */
-static int
-mptsas_start_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd)
+static void
+mptsas_accept_tx_waitq(mptsas_t *mpt)
 {
-        struct scsi_pkt         *pkt = CMD2PKT(cmd);
-        uint32_t                control = 0;
-        int                     n;
-        caddr_t                 mem;
-        pMpi2SCSIIORequest_t    io_request;
-        ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
-        ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
-        mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
-        uint16_t                SMID, io_flags = 0;
-        uint32_t                request_desc_low, request_desc_high;
+        mptsas_cmd_t *cmd;
 
-        NDBG1(("mptsas_start_cmd0: cmd=0x%p", (void *)cmd));
+        ASSERT(mutex_owned(&mpt->m_mutex));
+        ASSERT(mutex_owned(&mpt->m_tx_waitq_mutex));
 
         /*
-         * Set SMID and increment index.  Rollover to 1 instead of 0 if index
-         * is at the max.  0 is an invalid SMID, so we call the first index 1.
+         * A Bus Reset could occur at any time and flush the tx_waitq,
+         * so we cannot count on the tx_waitq to contain even one cmd.
+         * And when the m_tx_waitq_mutex is released and run
+         * mptsas_accept_pkt(), the tx_waitq may be flushed.
          */
-        SMID = cmd->cmd_slot;
-
-        /*
-         * It is possible for back to back device reset to
-         * happen before the reset delay has expired.  That's
-         * ok, just let the device reset go out on the bus.
-         */
-        if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
-                ASSERT(ptgt->m_reset_delay == 0);
-        }
-
-        /*
-         * if a non-tagged cmd is submitted to an active tagged target
-         * then drain before submitting this cmd; SCSI-2 allows RQSENSE
-         * to be untagged
-         */
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
-        if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
-            (ptgt->m_t_ncmds > 1) &&
-            ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
-            (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
-                if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
-                        NDBG23(("target=%d, untagged cmd, start draining\n",
-                            ptgt->m_devhdl));
-
-                        if (ptgt->m_reset_delay == 0) {
-                                mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
-                        }
-                        mutex_exit(&ptgt->m_tgt_intr_mutex);
-
-                        mutex_enter(&mpt->m_mutex);
-                        mptsas_remove_cmd(mpt, cmd);
-                        cmd->cmd_pkt_flags |= FLAG_HEAD;
-                        mptsas_waitq_add(mpt, cmd);
-                        mutex_exit(&mpt->m_mutex);
-                        return (DDI_FAILURE);
-                }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
-                return (DDI_FAILURE);
-        }
-        mutex_exit(&ptgt->m_tgt_intr_mutex);
-
-        /*
-         * Set correct tag bits.
-         */
-        if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
-                switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
-                    FLAG_TAGMASK) >> 12)]) {
-                case MSG_SIMPLE_QTAG:
-                        control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+        cmd = mpt->m_tx_waitq;
+        for (;;) {
+                if ((cmd = mpt->m_tx_waitq) == NULL) {
+                        mpt->m_tx_draining = 0;
                         break;
-                case MSG_HEAD_QTAG:
-                        control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
-                        break;
-                case MSG_ORDERED_QTAG:
-                        control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
-                        break;
-                default:
-                        mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
-                        break;
                 }
-        } else {
-                if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
-                                ptgt->m_t_throttle = 1;
+                if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL) {
+                        mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
                 }
-                control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+                cmd->cmd_linkp = NULL;
+                mutex_exit(&mpt->m_tx_waitq_mutex);
+                if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT)
+                        cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed "
+                            "to accept cmd on queue\n");
+                mutex_enter(&mpt->m_tx_waitq_mutex);
         }
+}
 
-        if (cmd->cmd_pkt_flags & FLAG_TLR) {
-                control |= MPI2_SCSIIO_CONTROL_TLR_ON;
-        }
 
-        mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
-        io_request = (pMpi2SCSIIORequest_t)mem;
-
-        bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
-        ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
-            (MPI2_SCSI_IO_REQUEST, SGL) / 4);
-        mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
-            MPI2_FUNCTION_SCSI_IO_REQUEST);
-
-        (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
-            io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
-
-        io_flags = cmd->cmd_cdblen;
-        ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
-        /*
-         * setup the Scatter/Gather DMA list for this request
+/*
+ * mpt tag type lookup
          */
-        if (cmd->cmd_cookiec > 0) {
-                mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
-        } else {
-                ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
-                    ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
-                    MPI2_SGE_FLAGS_END_OF_BUFFER |
-                    MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-                    MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
-        }
+static char mptsas_tag_lookup[] =
+        {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
 
-        /*
-         * save ARQ information
-         */
-        ddi_put8(acc_hdl, &io_request->SenseBufferLength, cmd->cmd_rqslen);
-        if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
-            (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
-                ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
-                    cmd->cmd_ext_arqcookie.dmac_address);
-        } else {
-                ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
-                    cmd->cmd_arqcookie.dmac_address);
-        }
-
-        ddi_put32(acc_hdl, &io_request->Control, control);
-
-        NDBG31(("starting message=0x%p, with cmd=0x%p",
-            (void *)(uintptr_t)mpt->m_req_frame_dma_addr, (void *)cmd));
-
-        (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
-
-        /*
-         * Build request descriptor and write it to the request desc post reg.
-         */
-        request_desc_low = (SMID << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
-        request_desc_high = ptgt->m_devhdl << 16;
-
-        mutex_enter(&mpt->m_mutex);
-        mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
-        MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
-        mutex_exit(&mpt->m_mutex);
-
-        /*
-         * Start timeout.
-         */
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
-#ifdef MPTSAS_TEST
-        /*
-         * Temporarily set timebase = 0;  needed for
-         * timeout torture test.
-         */
-        if (mptsas_test_timeouts) {
-                ptgt->m_timebase = 0;
-        }
-#endif
-        n = pkt->pkt_time - ptgt->m_timebase;
-
-        if (n == 0) {
-                (ptgt->m_dups)++;
-                ptgt->m_timeout = ptgt->m_timebase;
-        } else if (n > 0) {
-                ptgt->m_timeout =
-                    ptgt->m_timebase = pkt->pkt_time;
-                ptgt->m_dups = 1;
-        } else if (n < 0) {
-                ptgt->m_timeout = ptgt->m_timebase;
-        }
-#ifdef MPTSAS_TEST
-        /*
-         * Set back to a number higher than
-         * mptsas_scsi_watchdog_tick
-         * so timeouts will happen in mptsas_watchsubr
-         */
-        if (mptsas_test_timeouts) {
-                ptgt->m_timebase = 60;
-        }
-#endif
-        mutex_exit(&ptgt->m_tgt_intr_mutex);
-
-        if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
-            (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
-                ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
-                return (DDI_FAILURE);
-        }
-        return (DDI_SUCCESS);
-}
-
 static int
 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
 {
         struct scsi_pkt         *pkt = CMD2PKT(cmd);
         uint32_t                control = 0;

@@ -8446,11 +7863,10 @@
         /*
          * if a non-tagged cmd is submitted to an active tagged target
          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
          * to be untagged
          */
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
             (ptgt->m_t_ncmds > 1) &&
             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {

@@ -8458,21 +7874,17 @@
                             ptgt->m_devhdl));
 
                         if (ptgt->m_reset_delay == 0) {
                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
                         }
-                        mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                         mptsas_remove_cmd(mpt, cmd);
                         cmd->cmd_pkt_flags |= FLAG_HEAD;
                         mptsas_waitq_add(mpt, cmd);
-                        return (DDI_FAILURE);
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
                 return (DDI_FAILURE);
         }
-        mutex_exit(&ptgt->m_tgt_intr_mutex);
 
         /*
          * Set correct tag bits.
          */
         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {

@@ -8552,18 +7964,15 @@
         /*
          * Build request descriptor and write it to the request desc post reg.
          */
         request_desc_low = (SMID << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
         request_desc_high = ptgt->m_devhdl << 16;
-
-        mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
 
         /*
          * Start timeout.
          */
-        mutex_enter(&ptgt->m_tgt_intr_mutex);
 #ifdef MPTSAS_TEST
         /*
          * Temporarily set timebase = 0;  needed for
          * timeout torture test.
          */

@@ -8591,11 +8000,10 @@
          */
         if (mptsas_test_timeouts) {
                 ptgt->m_timebase = 60;
         }
 #endif
-        mutex_exit(&ptgt->m_tgt_intr_mutex);
 
         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
                 return (DDI_FAILURE);

@@ -8638,20 +8046,19 @@
         cv_signal(&mpt->m_doneq_thread_id[t].cv);
         mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
 }
 
 /*
- * move the current global doneq to the doneq of thread[t]
+ * move the current global doneq to the doneq of thead[t]
  */
 static void
 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
 {
         mptsas_cmd_t                    *cmd;
         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
 
         ASSERT(mutex_owned(&item->mutex));
-        mutex_enter(&mpt->m_intr_mutex);
         while ((cmd = mpt->m_doneq) != NULL) {
                 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
                         mpt->m_donetail = &mpt->m_doneq;
                 }
                 cmd->cmd_linkp = NULL;

@@ -8658,11 +8065,10 @@
                 *item->donetail = cmd;
                 item->donetail = &cmd->cmd_linkp;
                 mpt->m_doneq_len--;
                 item->len++;
         }
-        mutex_exit(&mpt->m_intr_mutex);
 }
 
 void
 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
 {

@@ -8733,25 +8139,32 @@
                 pkt->pkt_statistics = 0;
         }
 }
 
 /*
- * mptsas_doneq_add0 is similar to mptsas_doneq_add except that it is called
- * where m_intr_mutex has already been held.
+ * These routines manipulate the queue of commands that
+ * are waiting for their completion routines to be called.
+ * The queue is usually in FIFO order but on an MP system
+ * it's possible for the completion routines to get out
+ * of order. If that's a problem you need to add a global
+ * mutex around the code that calls the completion routine
+ * in the interrupt handler.
  */
-static inline void
-mptsas_doneq_add0(mptsas_t *mpt, mptsas_cmd_t *cmd)
+static void
+mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
 {
         struct scsi_pkt *pkt = CMD2PKT(cmd);
 
-        NDBG31(("mptsas_doneq_add0: cmd=0x%p", (void *)cmd));
+        NDBG31(("mptsas_doneq_add: cmd=0x%p", (void *)cmd));
 
         ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
         cmd->cmd_linkp = NULL;
         cmd->cmd_flags |= CFLAG_FINISHED;
         cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
 
+        mptsas_fma_check(mpt, cmd);
+
         /*
          * only add scsi pkts that have completion routines to
          * the doneq.  no intr cmds do not have callbacks.
          */
         if (pkt && (pkt->pkt_comp)) {

@@ -8759,31 +8172,10 @@
                 mpt->m_donetail = &cmd->cmd_linkp;
                 mpt->m_doneq_len++;
         }
 }
 
-/*
- * These routines manipulate the queue of commands that
- * are waiting for their completion routines to be called.
- * The queue is usually in FIFO order but on an MP system
- * it's possible for the completion routines to get out
- * of order. If that's a problem you need to add a global
- * mutex around the code that calls the completion routine
- * in the interrupt handler.
- */
-static void
-mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
-{
-        ASSERT(mutex_owned(&mpt->m_mutex));
-
-        mptsas_fma_check(mpt, cmd);
-
-        mutex_enter(&mpt->m_intr_mutex);
-        mptsas_doneq_add0(mpt, cmd);
-        mutex_exit(&mpt->m_intr_mutex);
-}
-
 static mptsas_cmd_t *
 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
 {
         mptsas_cmd_t                    *cmd;
         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];

@@ -8802,11 +8194,10 @@
 }
 
 static void
 mptsas_doneq_empty(mptsas_t *mpt)
 {
-        mutex_enter(&mpt->m_intr_mutex);
         if (mpt->m_doneq && !mpt->m_in_callback) {
                 mptsas_cmd_t    *cmd, *next;
                 struct scsi_pkt *pkt;
 
                 mpt->m_in_callback = 1;

@@ -8813,17 +8204,10 @@
                 cmd = mpt->m_doneq;
                 mpt->m_doneq = NULL;
                 mpt->m_donetail = &mpt->m_doneq;
                 mpt->m_doneq_len = 0;
 
-                mutex_exit(&mpt->m_intr_mutex);
-
-                /*
-                 * ONLY in ISR, is it called without m_mutex held, otherwise,
-                 * it is always called with m_mutex held.
-                 */
-                if ((curthread->t_flag & T_INTR_THREAD) == 0)
                         mutex_exit(&mpt->m_mutex);
                 /*
                  * run the completion routines of all the
                  * completed commands
                  */

@@ -8834,16 +8218,13 @@
                         cmd->cmd_flags |= CFLAG_COMPLETED;
                         pkt = CMD2PKT(cmd);
                         mptsas_pkt_comp(pkt, cmd);
                         cmd = next;
                 }
-                if ((curthread->t_flag & T_INTR_THREAD) == 0)
                         mutex_enter(&mpt->m_mutex);
                 mpt->m_in_callback = 0;
-                return;
         }
-        mutex_exit(&mpt->m_intr_mutex);
 }
 
 /*
  * These routines manipulate the target's queue of pending requests
  */

@@ -8854,16 +8235,14 @@
         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
         cmd->cmd_queued = TRUE;
         if (ptgt)
                 ptgt->m_t_nwait++;
         if (cmd->cmd_pkt_flags & FLAG_HEAD) {
-                mutex_enter(&mpt->m_intr_mutex);
                 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
                         mpt->m_waitqtail = &cmd->cmd_linkp;
                 }
                 mpt->m_waitq = cmd;
-                mutex_exit(&mpt->m_intr_mutex);
         } else {
                 cmd->cmd_linkp = NULL;
                 *(mpt->m_waitqtail) = cmd;
                 mpt->m_waitqtail = &cmd->cmd_linkp;
         }

@@ -8874,13 +8253,11 @@
 {
         mptsas_cmd_t    *cmd;
         mptsas_target_t *ptgt;
         NDBG7(("mptsas_waitq_rm"));
 
-        mutex_enter(&mpt->m_intr_mutex);
         MPTSAS_WAITQ_RM(mpt, cmd);
-        mutex_exit(&mpt->m_intr_mutex);
 
         NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
         if (cmd) {
                 ptgt = cmd->cmd_tgt_addr;
                 if (ptgt) {

@@ -8906,14 +8283,12 @@
                 ptgt->m_t_nwait--;
                 ASSERT(ptgt->m_t_nwait >= 0);
         }
 
         if (prevp == cmd) {
-                mutex_enter(&mpt->m_intr_mutex);
                 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
                         mpt->m_waitqtail = &mpt->m_waitq;
-                mutex_exit(&mpt->m_intr_mutex);
 
                 cmd->cmd_linkp = NULL;
                 cmd->cmd_queued = FALSE;
                 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
                     (void *)mpt, (void *)cmd));

@@ -8934,11 +8309,62 @@
                 prevp = prevp->cmd_linkp;
         }
         cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
 }
 
+static mptsas_cmd_t *
+mptsas_tx_waitq_rm(mptsas_t *mpt)
+{
+        mptsas_cmd_t *cmd;
+        NDBG7(("mptsas_tx_waitq_rm"));
+
+        MPTSAS_TX_WAITQ_RM(mpt, cmd);
+
+        NDBG7(("mptsas_tx_waitq_rm: cmd=0x%p", (void *)cmd));
+
+        return (cmd);
+}
+
 /*
+ * remove specified cmd from the middle of the tx_waitq.
+ */
+static void
+mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
+{
+        mptsas_cmd_t *prevp = mpt->m_tx_waitq;
+
+        NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
+            (void *)mpt, (void *)cmd));
+
+        if (prevp == cmd) {
+                if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL)
+                        mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
+
+                cmd->cmd_linkp = NULL;
+                cmd->cmd_queued = FALSE;
+                NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
+                    (void *)mpt, (void *)cmd));
+                return;
+        }
+
+        while (prevp != NULL) {
+                if (prevp->cmd_linkp == cmd) {
+                        if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
+                                mpt->m_tx_waitqtail = &prevp->cmd_linkp;
+
+                        cmd->cmd_linkp = NULL;
+                        cmd->cmd_queued = FALSE;
+                        NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
+                            (void *)mpt, (void *)cmd));
+                        return;
+                }
+                prevp = prevp->cmd_linkp;
+        }
+        cmn_err(CE_PANIC, "mpt: mptsas_tx_waitq_delete: queue botch");
+}
+
+/*
  * device and bus reset handling
  *
  * Notes:
  *      - RESET_ALL:    reset the controller
  *      - RESET_TARGET: reset the target specified in scsi_address

@@ -9097,27 +8523,34 @@
          * Make sure the I/O Controller has flushed all cmds
          * that are associated with this target for a target reset
          * and target/lun for abort task set.
          * Account for TM requests, which use the last SMID.
          */
-        mutex_enter(&mpt->m_intr_mutex);
         for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
-                if ((cmd = slots->m_slot[slot]) == NULL) {
+                if ((cmd = slots->m_slot[slot]) == NULL)
                         continue;
-                }
                 reason = CMD_RESET;
                 stat = STAT_DEV_RESET;
                 switch (tasktype) {
                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
                         if (Tgt(cmd) == target) {
+                                if (cmd->cmd_tgt_addr->m_timeout < 0) {
+                                        /*
+                                         * When timeout requested, propagate
+                                         * proper reason and statistics to
+                                         * target drivers.
+                                         */
+                                        reason = CMD_TIMEOUT;
+                                        stat |= STAT_TIMEOUT;
+                                }
                                 NDBG25(("mptsas_flush_target discovered non-"
                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
                                     tasktype));
                                 mptsas_dump_cmd(mpt, cmd);
-                                mptsas_remove_cmd0(mpt, cmd);
+                                mptsas_remove_cmd(mpt, cmd);
                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
-                                mptsas_doneq_add0(mpt, cmd);
+                                mptsas_doneq_add(mpt, cmd);
                         }
                         break;
                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
                         reason = CMD_ABORTED;
                         stat = STAT_ABORTED;

@@ -9127,24 +8560,23 @@
 
                                 NDBG25(("mptsas_flush_target discovered non-"
                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
                                     tasktype));
                                 mptsas_dump_cmd(mpt, cmd);
-                                mptsas_remove_cmd0(mpt, cmd);
+                                mptsas_remove_cmd(mpt, cmd);
                                 mptsas_set_pkt_reason(mpt, cmd, reason,
                                     stat);
-                                mptsas_doneq_add0(mpt, cmd);
+                                mptsas_doneq_add(mpt, cmd);
                         }
                         break;
                 default:
                         break;
                 }
         }
-        mutex_exit(&mpt->m_intr_mutex);
 
         /*
-         * Flush the waitq of this target's cmds
+         * Flush the waitq and tx_waitq of this target's cmds
          */
         cmd = mpt->m_waitq;
 
         reason = CMD_RESET;
         stat = STAT_DEV_RESET;

@@ -9159,10 +8591,25 @@
                                     reason, stat);
                                 mptsas_doneq_add(mpt, cmd);
                         }
                         cmd = next_cmd;
                 }
+                mutex_enter(&mpt->m_tx_waitq_mutex);
+                cmd = mpt->m_tx_waitq;
+                while (cmd != NULL) {
+                        next_cmd = cmd->cmd_linkp;
+                        if (Tgt(cmd) == target) {
+                                mptsas_tx_waitq_delete(mpt, cmd);
+                                mutex_exit(&mpt->m_tx_waitq_mutex);
+                                mptsas_set_pkt_reason(mpt, cmd,
+                                    reason, stat);
+                                mptsas_doneq_add(mpt, cmd);
+                                mutex_enter(&mpt->m_tx_waitq_mutex);
+                        }
+                        cmd = next_cmd;
+                }
+                mutex_exit(&mpt->m_tx_waitq_mutex);
                 break;
         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
                 reason = CMD_ABORTED;
                 stat =  STAT_ABORTED;
                 /*FALLTHROUGH*/

@@ -9175,10 +8622,25 @@
                                     reason, stat);
                                 mptsas_doneq_add(mpt, cmd);
                         }
                         cmd = next_cmd;
                 }
+                mutex_enter(&mpt->m_tx_waitq_mutex);
+                cmd = mpt->m_tx_waitq;
+                while (cmd != NULL) {
+                        next_cmd = cmd->cmd_linkp;
+                        if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
+                                mptsas_tx_waitq_delete(mpt, cmd);
+                                mutex_exit(&mpt->m_tx_waitq_mutex);
+                                mptsas_set_pkt_reason(mpt, cmd,
+                                    reason, stat);
+                                mptsas_doneq_add(mpt, cmd);
+                                mutex_enter(&mpt->m_tx_waitq_mutex);
+                        }
+                        cmd = next_cmd;
+                }
+                mutex_exit(&mpt->m_tx_waitq_mutex);
                 break;
         default:
                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
                     tasktype);
                 break;

@@ -9202,15 +8664,13 @@
          * The I/O Controller should have already sent back
          * all commands via the scsi I/O reply frame.  Make
          * sure all commands have been flushed.
          * Account for TM request, which use the last SMID.
          */
-        mutex_enter(&mpt->m_intr_mutex);
         for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
-                if ((cmd = slots->m_slot[slot]) == NULL) {
+                if ((cmd = slots->m_slot[slot]) == NULL)
                         continue;
-                }
 
                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
                         /*
                          * Need to make sure to tell everyone that might be
                          * waiting on this command that it's going to fail.  If

@@ -9234,15 +8694,14 @@
 
                 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
                     slot));
                 mptsas_dump_cmd(mpt, cmd);
 
-                mptsas_remove_cmd0(mpt, cmd);
+                mptsas_remove_cmd(mpt, cmd);
                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
-                mptsas_doneq_add0(mpt, cmd);
+                mptsas_doneq_add(mpt, cmd);
         }
-        mutex_exit(&mpt->m_intr_mutex);
 
         /*
          * Flush the waitq.
          */
         while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {

@@ -9256,10 +8715,30 @@
                         cv_broadcast(&mpt->m_fw_diag_cv);
                 } else {
                         mptsas_doneq_add(mpt, cmd);
                 }
         }
+
+        /*
+         * Flush the tx_waitq
+         */
+        mutex_enter(&mpt->m_tx_waitq_mutex);
+        while ((cmd = mptsas_tx_waitq_rm(mpt)) != NULL) {
+                mutex_exit(&mpt->m_tx_waitq_mutex);
+                mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
+                mptsas_doneq_add(mpt, cmd);
+                mutex_enter(&mpt->m_tx_waitq_mutex);
+        }
+        mutex_exit(&mpt->m_tx_waitq_mutex);
+
+        /*
+         * Drain the taskqs prior to reallocating resources.
+         */
+        mutex_exit(&mpt->m_mutex);
+        ddi_taskq_wait(mpt->m_event_taskq);
+        ddi_taskq_wait(mpt->m_dr_taskq);
+        mutex_enter(&mpt->m_mutex);
 }
 
 /*
  * set pkt_reason and OR in pkt_statistics flag
  */

@@ -9304,14 +8783,12 @@
 
         NDBG22(("mptsas_setup_bus_reset_delay"));
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
 

@@ -9365,11 +8842,10 @@
         ASSERT(mutex_owned(&mpt->m_mutex));
 
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 if (ptgt->m_reset_delay != 0) {
                         ptgt->m_reset_delay -=
                             MPTSAS_WATCH_RESET_DELAY_TICK;
                         if (ptgt->m_reset_delay <= 0) {
                                 ptgt->m_reset_delay = 0;

@@ -9378,11 +8854,10 @@
                                 restart++;
                         } else {
                                 done = -1;
                         }
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
 

@@ -9474,13 +8949,12 @@
                 }
 
                 /*
                  * Have mpt firmware abort this command
                  */
-                mutex_enter(&mpt->m_intr_mutex);
+
                 if (slots->m_slot[sp->cmd_slot] != NULL) {
-                        mutex_exit(&mpt->m_intr_mutex);
                         rval = mptsas_ioc_task_management(mpt,
                             MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
                             lun, NULL, 0, 0);
 
                         /*

@@ -9490,11 +8964,10 @@
                          */
                         if (rval == FAILED)
                                 rval = FALSE;
                         goto done;
                 }
-                mutex_exit(&mpt->m_intr_mutex);
         }
 
         /*
          * If pkt is NULL then abort task set
          */

@@ -9602,11 +9075,10 @@
 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
 {
         mptsas_t        *mpt = ADDR2MPT(ap);
         int             ckey;
         int             rval = FALSE;
-        mptsas_target_t *ptgt;
 
         NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
             ap->a_target, cap, value, tgtonly));
 
         if (!tgtonly) {

@@ -9642,15 +9114,13 @@
                 } else {
                         rval = FALSE;
                 }
                 break;
         case SCSI_CAP_TAGGED_QING:
-                ptgt = ((mptsas_tgt_private_t *)
-                    (ap->a_hba_tran->tran_tgt_private))->t_private;
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
-                mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
+                mptsas_set_throttle(mpt, ((mptsas_tgt_private_t *)
+                    (ap->a_hba_tran->tran_tgt_private))->t_private,
+                    MAX_THROTTLE);
                 rval = TRUE;
                 break;
         case SCSI_CAP_QFULL_RETRIES:
                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
                     t_private->m_qfull_retries = (uchar_t)value;

@@ -9690,17 +9160,17 @@
 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
 {
         mptsas_slots_t  *old_active = mpt->m_active;
         mptsas_slots_t  *new_active;
         size_t          size;
-        int             rval = -1, nslot, i;
-        mptsas_slot_free_e_t    *pe;
+        int             rval = -1, i;
 
-        if (mptsas_outstanding_cmds_n(mpt)) {
-                NDBG9(("cannot change size of active slots array"));
-                return (rval);
-        }
+        /*
+         * if there are active commands, then we cannot
+         * change size of active slots array.
+         */
+        ASSERT(mpt->m_ncmds == 0);
 
         size = MPTSAS_SLOTS_SIZE(mpt);
         new_active = kmem_zalloc(size, flag);
         if (new_active == NULL) {
                 NDBG1(("new active alloc failed"));

@@ -9709,14 +9179,13 @@
         /*
          * Since SMID 0 is reserved and the TM slot is reserved, the
          * number of slots that can be used at any one time is
          * m_max_requests - 2.
          */
-        new_active->m_n_slots = nslot = (mpt->m_max_requests - 2);
+        new_active->m_n_slots = (mpt->m_max_requests - 2);
         new_active->m_size = size;
         new_active->m_tags = 1;
-
         if (old_active) {
                 new_active->m_tgttbl = old_active->m_tgttbl;
                 new_active->m_smptbl = old_active->m_smptbl;
                 new_active->m_num_raid_configs =
                     old_active->m_num_raid_configs;

@@ -9724,66 +9193,10 @@
                         new_active->m_raidconfig[i] =
                             old_active->m_raidconfig[i];
                 }
                 mptsas_free_active_slots(mpt);
         }
-
-        if (max_ncpus & (max_ncpus - 1)) {
-                mpt->m_slot_freeq_pair_n = (1 << highbit(max_ncpus));
-        } else {
-                mpt->m_slot_freeq_pair_n = max_ncpus;
-        }
-        mpt->m_slot_freeq_pairp = kmem_zalloc(
-            mpt->m_slot_freeq_pair_n *
-            sizeof (mptsas_slot_freeq_pair_t), KM_SLEEP);
-        for (i = 0; i < mpt->m_slot_freeq_pair_n; i++) {
-                list_create(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_allocq.s.m_fq_list,
-                    sizeof (mptsas_slot_free_e_t),
-                    offsetof(mptsas_slot_free_e_t, node));
-                list_create(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_releq.s.m_fq_list,
-                    sizeof (mptsas_slot_free_e_t),
-                    offsetof(mptsas_slot_free_e_t, node));
-                mpt->m_slot_freeq_pairp[i].m_slot_allocq.s.m_fq_n = 0;
-                mpt->m_slot_freeq_pairp[i].m_slot_releq.s.m_fq_n = 0;
-                mutex_init(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_allocq.s.m_fq_mutex, NULL, MUTEX_DRIVER,
-                    DDI_INTR_PRI(mpt->m_intr_pri));
-                mutex_init(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_releq.s.m_fq_mutex, NULL, MUTEX_DRIVER,
-                    DDI_INTR_PRI(mpt->m_intr_pri));
-        }
-        pe = mpt->m_slot_free_ae = kmem_zalloc(nslot *
-            sizeof (mptsas_slot_free_e_t), KM_SLEEP);
-        /*
-         * An array of Mpi2ReplyDescriptorsUnion_t is defined here.
-         * We are trying to eliminate the m_mutex in the context
-         * reply code path in the ISR. Since the read of the
-         * ReplyDescriptor and update/write of the ReplyIndex must
-         * be atomic (since the poll thread may also update them at
-         * the same time) so we first read out of the ReplyDescriptor
-         * into this array and update the ReplyIndex register with a
-         * separate mutex m_intr_mutex protected, and then release the
-         * mutex and process all of them. the length of the array is
-         * defined as max as 128(128*64=8k), which is
-         * assumed as the maxmium depth of the interrupt coalese.
-         */
-        mpt->m_reply = kmem_zalloc(MPI_ADDRESS_COALSCE_MAX *
-            sizeof (Mpi2ReplyDescriptorsUnion_t), KM_SLEEP);
-        for (i = 0; i < nslot; i++, pe++) {
-                pe->slot = i + 1; /* SMID 0 is reserved */
-                pe->cpuid = i % mpt->m_slot_freeq_pair_n;
-                list_insert_tail(&mpt->m_slot_freeq_pairp
-                    [i % mpt->m_slot_freeq_pair_n]
-                    .m_slot_allocq.s.m_fq_list, pe);
-                mpt->m_slot_freeq_pairp[i % mpt->m_slot_freeq_pair_n]
-                    .m_slot_allocq.s.m_fq_n++;
-                mpt->m_slot_freeq_pairp[i % mpt->m_slot_freeq_pair_n]
-                    .m_slot_allocq.s.m_fq_n_init++;
-        }
-
         mpt->m_active = new_active;
         rval = 0;
 
         return (rval);
 }

@@ -9791,48 +9204,13 @@
 static void
 mptsas_free_active_slots(mptsas_t *mpt)
 {
         mptsas_slots_t  *active = mpt->m_active;
         size_t          size;
-        mptsas_slot_free_e_t    *pe;
-        int     i;
 
         if (active == NULL)
                 return;
-
-        if (mpt->m_slot_freeq_pairp) {
-                for (i = 0; i < mpt->m_slot_freeq_pair_n; i++) {
-                        while ((pe = list_head(&mpt->m_slot_freeq_pairp
-                            [i].m_slot_allocq.s.m_fq_list)) != NULL) {
-                                list_remove(&mpt->m_slot_freeq_pairp[i]
-                                    .m_slot_allocq.s.m_fq_list, pe);
-                        }
-                        list_destroy(&mpt->m_slot_freeq_pairp
-                            [i].m_slot_allocq.s.m_fq_list);
-                        while ((pe = list_head(&mpt->m_slot_freeq_pairp
-                            [i].m_slot_releq.s.m_fq_list)) != NULL) {
-                                list_remove(&mpt->m_slot_freeq_pairp[i]
-                                    .m_slot_releq.s.m_fq_list, pe);
-                        }
-                        list_destroy(&mpt->m_slot_freeq_pairp
-                            [i].m_slot_releq.s.m_fq_list);
-                        mutex_destroy(&mpt->m_slot_freeq_pairp
-                            [i].m_slot_allocq.s.m_fq_mutex);
-                        mutex_destroy(&mpt->m_slot_freeq_pairp
-                            [i].m_slot_releq.s.m_fq_mutex);
-                }
-                kmem_free(mpt->m_slot_freeq_pairp, mpt->m_slot_freeq_pair_n *
-                    sizeof (mptsas_slot_freeq_pair_t));
-        }
-        if (mpt->m_slot_free_ae)
-                kmem_free(mpt->m_slot_free_ae, mpt->m_active->m_n_slots *
-                    sizeof (mptsas_slot_free_e_t));
-
-        if (mpt->m_reply)
-                kmem_free(mpt->m_reply, MPI_ADDRESS_COALSCE_MAX *
-                    sizeof (Mpi2ReplyDescriptorsUnion_t));
-
         size = active->m_size;
         kmem_free(active, size);
         mpt->m_active = NULL;
 }
 

@@ -9975,11 +9353,10 @@
 
         /*
          * Check for commands stuck in active slot
          * Account for TM requests, which use the last SMID.
          */
-        mutex_enter(&mpt->m_intr_mutex);
         for (i = 0; i <= mpt->m_active->m_n_slots; i++) {
                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
                         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
                                 cmd->cmd_active_timeout -=
                                     mptsas_scsi_watchdog_tick;

@@ -9986,15 +9363,13 @@
                                 if (cmd->cmd_active_timeout <= 0) {
                                         /*
                                          * There seems to be a command stuck
                                          * in the active slot.  Drain throttle.
                                          */
-                                        ptgt = cmd->cmd_tgt_addr;
-                                        mutex_enter(&ptgt->m_tgt_intr_mutex);
-                                        mptsas_set_throttle(mpt, ptgt,
+                                        mptsas_set_throttle(mpt,
+                                            cmd->cmd_tgt_addr,
                                             DRAIN_THROTTLE);
-                                        mutex_exit(&ptgt->m_tgt_intr_mutex);
                                 }
                         }
                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
                             (cmd->cmd_flags & CFLAG_CONFIG) ||
                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {

@@ -10011,23 +9386,15 @@
                                         cv_broadcast(&mpt->m_fw_diag_cv);
                                 }
                         }
                 }
         }
-        mutex_exit(&mpt->m_intr_mutex);
 
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
                 /*
-                 * In order to avoid using m_mutex in the key code path in ISR,
-                 * separate mutexs are introduced to protect those elements
-                 * shown in ISR.
-                 */
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
-
-                /*
                  * If we were draining due to a qfull condition,
                  * go back to full throttle.
                  */
                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&

@@ -10041,21 +9408,36 @@
 
                         if (ptgt->m_timebase <=
                             mptsas_scsi_watchdog_tick) {
                                 ptgt->m_timebase +=
                                     mptsas_scsi_watchdog_tick;
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
                                 continue;
                         }
 
                         ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
 
+                        if (ptgt->m_timeout_count > 0) {
+                                ptgt->m_timeout_interval +=
+                                    mptsas_scsi_watchdog_tick;
+                        }
+                        if (ptgt->m_timeout_interval >
+                            mptsas_timeout_interval) {
+                                ptgt->m_timeout_interval = 0;
+                                ptgt->m_timeout_count = 0;
+                        }
+
                         if (ptgt->m_timeout < 0) {
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
+                                ptgt->m_timeout_count++;
+                                if (ptgt->m_timeout_count >
+                                    mptsas_timeout_threshold) {
+                                        ptgt->m_timeout_count = 0;
+                                        mptsas_kill_target(mpt, ptgt);
+                                } else {
                                 mptsas_cmd_timeout(mpt, ptgt->m_devhdl);
+                                }
                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
                                 continue;
                         }
 

@@ -10064,11 +9446,11 @@
                                 NDBG23(("pending timeout"));
                                 mptsas_set_throttle(mpt, ptgt,
                                     DRAIN_THROTTLE);
                         }
                 }
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
+
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
 }
 

@@ -10093,10 +9475,44 @@
                     "recovery failed!", devhdl);
         }
 }
 
 /*
+ * target causing too many timeouts
+ */
+static void
+mptsas_kill_target(mptsas_t *mpt, mptsas_target_t *ptgt)
+{
+        mptsas_topo_change_list_t       *topo_node = NULL;
+
+        NDBG29(("mptsas_tgt_kill: target=%d", ptgt->m_devhdl));
+        mptsas_log(mpt, CE_WARN, "timeout threshold exceeded for "
+            "Target %d", ptgt->m_devhdl);
+
+        topo_node = kmem_zalloc(sizeof (mptsas_topo_change_list_t), KM_SLEEP);
+        topo_node->mpt = mpt;
+        topo_node->un.phymask = ptgt->m_phymask;
+        topo_node->event = MPTSAS_DR_EVENT_OFFLINE_TARGET;
+        topo_node->devhdl = ptgt->m_devhdl;
+        if (ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
+                topo_node->flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
+        else
+                topo_node->flags = MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
+        topo_node->object = NULL;
+
+        /*
+         * Launch DR taskq to fake topology change
+         */
+        if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
+            mptsas_handle_dr, (void *)topo_node,
+            DDI_NOSLEEP)) != DDI_SUCCESS) {
+                mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
+                    "for fake offline event failed. \n");
+        }
+}
+
+/*
  * Device / Hotplug control
  */
 static int
 mptsas_scsi_quiesce(dev_info_t *dip)
 {

@@ -10133,22 +9549,18 @@
 
         /* Set all the throttles to zero */
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
 
         /* If there are any outstanding commands in the queue */
-        mutex_enter(&mpt->m_intr_mutex);
-        if (mptsas_outstanding_cmds_n(mpt)) {
-                mutex_exit(&mpt->m_intr_mutex);
+        if (mpt->m_ncmds) {
                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
                         /*

@@ -10156,13 +9568,11 @@
                          */
                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
                         while (ptgt != NULL) {
-                                mutex_enter(&ptgt->m_tgt_intr_mutex);
                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
                         }
                         mptsas_restart_hba(mpt);

@@ -10182,11 +9592,10 @@
                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
                         mutex_exit(&mpt->m_mutex);
                         return (0);
                 }
         }
-        mutex_exit(&mpt->m_intr_mutex);
         /* Bus was not busy - QUIESCED */
         mutex_exit(&mpt->m_mutex);
 
         return (0);
 }

@@ -10200,13 +9609,11 @@
         mutex_enter(&mpt->m_mutex);
         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
         mptsas_restart_hba(mpt);

@@ -10221,35 +9628,30 @@
         mptsas_target_t *ptgt = NULL;
 
         mutex_enter(&mpt->m_mutex);
         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
                 mpt->m_quiesce_timeid = 0;
-                mutex_enter(&mpt->m_intr_mutex);
-                if (mptsas_outstanding_cmds_n(mpt)) {
-                        mutex_exit(&mpt->m_intr_mutex);
+                if (mpt->m_ncmds == 0) {
+                        /* Command queue has been drained */
+                        cv_signal(&mpt->m_cv);
+                } else {
                         /*
                          * The throttle may have been reset because
                          * of a SCSI bus reset
                          */
                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
                         while (ptgt != NULL) {
-                                mutex_enter(&ptgt->m_tgt_intr_mutex);
                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
-                                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
                         }
 
                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
                             drv_usectohz(1000000)));
-                } else {
-                        mutex_exit(&mpt->m_intr_mutex);
-                        /* Command queue has been drained */
-                        cv_signal(&mpt->m_cv);
                 }
         }
         mutex_exit(&mpt->m_mutex);
 }
 

@@ -10409,11 +9811,10 @@
          * finish.
          */
         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
         request_desc_low = (cmd->cmd_slot << 16) + desc_type;
         cmd->cmd_rfm = NULL;
-        mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
         }

@@ -10840,11 +10241,10 @@
         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
             DDI_DMA_SYNC_FORDEV);
         request_desc_low = (cmd->cmd_slot << 16) +
             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
         cmd->cmd_rfm = NULL;
-        mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
         MPTSAS_START_CMD(mpt, request_desc_low, 0);
         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
             DDI_SUCCESS) ||
             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
             DDI_SUCCESS)) {

@@ -11963,14 +11363,10 @@
         int                     copylen;
 
         int                     iport_flag = 0;
         dev_info_t              *dip = NULL;
         mptsas_phymask_t        phymask = 0;
-        struct devctl_iocdata   *dcp = NULL;
-        uint32_t                slotstatus = 0;
-        char                    *addr = NULL;
-        mptsas_target_t         *ptgt = NULL;
 
         *rval = MPTIOCTL_STATUS_GOOD;
         if (secpolicy_sys_config(credp, B_FALSE) != 0) {
                 return (EPERM);
         }

@@ -12008,70 +11404,12 @@
                 mutex_exit(&mpt->m_mutex);
         }
 
         if (iport_flag) {
                 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
-                if (status != 0) {
                         goto out;
                 }
-                /*
-                 * The following code control the OK2RM LED, it doesn't affect
-                 * the ioctl return status.
-                 */
-                if ((cmd == DEVCTL_DEVICE_ONLINE) ||
-                    (cmd == DEVCTL_DEVICE_OFFLINE)) {
-                        if (ndi_dc_allochdl((void *)data, &dcp) !=
-                            NDI_SUCCESS) {
-                                goto out;
-                        }
-                        addr = ndi_dc_getaddr(dcp);
-                        ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
-                        if (ptgt == NULL) {
-                                NDBG14(("mptsas_ioctl led control: tgt %s not "
-                                    "found", addr));
-                                ndi_dc_freehdl(dcp);
-                                goto out;
-                        }
-                        mutex_enter(&mpt->m_mutex);
-                        if (cmd == DEVCTL_DEVICE_ONLINE) {
-                                ptgt->m_tgt_unconfigured = 0;
-                        } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
-                                ptgt->m_tgt_unconfigured = 1;
-                        }
-                        slotstatus = 0;
-#ifdef MPTSAS_GET_LED
-                        /*
-                         * The get led status can't get a valid/reasonable
-                         * state, so ignore the get led status, and write the
-                         * required value directly
-                         */
-                        if (mptsas_get_led_status(mpt, ptgt, &slotstatus) !=
-                            DDI_SUCCESS) {
-                                NDBG14(("mptsas_ioctl: get LED for tgt %s "
-                                    "failed %x", addr, slotstatus));
-                                slotstatus = 0;
-                        }
-                        NDBG14(("mptsas_ioctl: LED status %x for %s",
-                            slotstatus, addr));
-#endif
-                        if (cmd == DEVCTL_DEVICE_OFFLINE) {
-                                slotstatus |=
-                                    MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
-                        } else {
-                                slotstatus &=
-                                    ~MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
-                        }
-                        if (mptsas_set_led_status(mpt, ptgt, slotstatus) !=
-                            DDI_SUCCESS) {
-                                NDBG14(("mptsas_ioctl: set LED for tgt %s "
-                                    "failed %x", addr, slotstatus));
-                        }
-                        mutex_exit(&mpt->m_mutex);
-                        ndi_dc_freehdl(dcp);
-                }
-                goto out;
-        }
         switch (cmd) {
                 case MPTIOCTL_UPDATE_FLASH:
                         if (ddi_copyin((void *)data, &flashdata,
                                 sizeof (struct mptsas_update_flash), mode)) {
                                 status = EFAULT;

@@ -12223,12 +11561,10 @@
                             rval);
                         break;
         }
 
 out:
-        if (mpt->m_options & MPTSAS_OPT_PM)
-                (void) pm_idle_component(mpt->m_dip, 0);
         return (status);
 }
 
 int
 mptsas_restart_ioc(mptsas_t *mpt)

@@ -12251,13 +11587,11 @@
          * Set all throttles to HOLD
          */
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
 

@@ -12265,11 +11599,12 @@
          * Disable interrupts
          */
         MPTSAS_DISABLE_INTR(mpt);
 
         /*
-         * Abort all commands: outstanding commands, commands in waitq
+         * Abort all commands: outstanding commands, commands in waitq and
+         * tx_waitq.
          */
         mptsas_flush_hba(mpt);
 
         /*
          * Reinitialize the chip.

@@ -12294,13 +11629,11 @@
          * Reset the throttles
          */
         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
             MPTSAS_HASH_FIRST);
         while (ptgt != NULL) {
-                mutex_enter(&ptgt->m_tgt_intr_mutex);
                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
-                mutex_exit(&ptgt->m_tgt_intr_mutex);
 
                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
         }
 

@@ -12606,13 +11939,11 @@
          */
         (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
         pmc[0] = pmc_name;
         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
             "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
-                mutex_enter(&mpt->m_intr_mutex);
                 mpt->m_options &= ~MPTSAS_OPT_PM;
-                mutex_exit(&mpt->m_intr_mutex);
                 mptsas_log(mpt, CE_WARN,
                     "mptsas%d: pm-component property creation failed.",
                     mpt->m_instance);
                 return (DDI_FAILURE);
         }

@@ -12631,13 +11962,11 @@
         }
         if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
                 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
                 return (DDI_FAILURE);
         }
-        mutex_enter(&mpt->m_intr_mutex);
         mpt->m_power_level = PM_LEVEL_D0;
-        mutex_exit(&mpt->m_intr_mutex);
         /*
          * Set pm idle delay.
          */
         mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
             mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);

@@ -12722,11 +12051,11 @@
                     "ret %d avail %d\n", ret, avail);
 
                 return (DDI_FAILURE);
         }
 
-        if (avail < count) {
+        if (0 && avail < count) {
                 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
                     "navail() returned %d", count, avail);
         }
 
         /* Mpt only have one interrupt routine */

@@ -13074,11 +12403,11 @@
                 }
         }
 
         phymask = mptsas_physport_to_phymask(mpt, physport);
         *pptgt = mptsas_tgt_alloc(&slots->m_tgttbl, *dev_handle, sas_wwn,
-            dev_info, phymask, phynum, mpt);
+            dev_info, phymask, phynum);
         if (*pptgt == NULL) {
                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
                     "structure!");
                 rval = DEV_INFO_FAIL_ALLOC;
                 return (rval);

@@ -14528,14 +13857,10 @@
                                 (void) ddi_prop_free(old_guid);
                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
                                     (!MDI_PI_IS_STANDBY(*pip)) &&
                                     (ptgt->m_tgt_unconfigured == 0)) {
                                         rval = mdi_pi_online(*pip, 0);
-                                        mutex_enter(&mpt->m_mutex);
-                                        (void) mptsas_set_led_status(mpt, ptgt,
-                                            0);
-                                        mutex_exit(&mpt->m_mutex);
                                 } else {
                                         rval = DDI_SUCCESS;
                                 }
                                 if (rval != DDI_SUCCESS) {
                                         mptsas_log(mpt, CE_WARN, "path:target: "

@@ -14785,19 +14110,10 @@
                         mdi_rtn = MDI_FAILURE;
                         goto virt_create_done;
                 }
                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
                 mdi_rtn = mdi_pi_online(*pip, 0);
-                if (mdi_rtn == MDI_SUCCESS) {
-                        mutex_enter(&mpt->m_mutex);
-                        if (mptsas_set_led_status(mpt, ptgt, 0) !=
-                            DDI_SUCCESS) {
-                                NDBG14(("mptsas: clear LED for slot %x "
-                                    "failed", ptgt->m_slot_num));
-                        }
-                        mutex_exit(&mpt->m_mutex);
-                }
                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
                         mdi_rtn = MDI_FAILURE;
                 }
 virt_create_done:
                 if (*pip && mdi_rtn != MDI_SUCCESS) {

@@ -15147,19 +14463,10 @@
                         /*
                          * Try to online the new node
                          */
                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
                 }
-                if (ndi_rtn == NDI_SUCCESS) {
-                        mutex_enter(&mpt->m_mutex);
-                        if (mptsas_set_led_status(mpt, ptgt, 0) !=
-                            DDI_SUCCESS) {
-                                NDBG14(("mptsas: clear LED for tgt %x "
-                                    "failed", ptgt->m_slot_num));
-                        }
-                        mutex_exit(&mpt->m_mutex);
-                }
 
                 /*
                  * If success set rtn flag, else unwire alloc'd lun
                  */
                 if (ndi_rtn != NDI_SUCCESS) {

@@ -15782,11 +15089,11 @@
         return (data);
 }
 
 mptsas_target_t *
 mptsas_tgt_alloc(mptsas_hash_table_t *hashtab, uint16_t devhdl, uint64_t wwid,
-    uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum, mptsas_t *mpt)
+    uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
 {
         mptsas_target_t *tmp_tgt = NULL;
 
         tmp_tgt = mptsas_hash_search(hashtab, wwid, phymask);
         if (tmp_tgt != NULL) {

@@ -15808,12 +15115,10 @@
         /* Initialized the tgt structure */
         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
         tmp_tgt->m_qfull_retry_interval =
             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
         tmp_tgt->m_t_throttle = MAX_THROTTLE;
-        mutex_init(&tmp_tgt->m_tgt_intr_mutex, NULL, MUTEX_DRIVER,
-            DDI_INTR_PRI(mpt->m_intr_pri));
 
         mptsas_hash_add(hashtab, tmp_tgt);
 
         return (tmp_tgt);
 }

@@ -15825,11 +15130,10 @@
         mptsas_target_t *tmp_tgt;
         tmp_tgt = mptsas_hash_rem(hashtab, wwid, phymask);
         if (tmp_tgt == NULL) {
                 cmn_err(CE_WARN, "Tgt not found, nothing to free");
         } else {
-                mutex_destroy(&tmp_tgt->m_tgt_intr_mutex);
                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
         }
 }
 
 /*

@@ -16032,102 +15336,11 @@
             "phymask", 0);
         *phymask = (mptsas_phymask_t)prop;
         ddi_release_devi(dip);
         return (dip);
 }
-static mptsas_target_t *
-mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
-{
-        uint8_t                 phynum;
-        uint64_t                wwn;
-        int                     lun;
-        mptsas_target_t         *ptgt = NULL;
 
-        if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
-                return (NULL);
-        }
-        if (addr[0] == 'w') {
-                ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
-        } else {
-                ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
-        }
-        return (ptgt);
-}
-
-#ifdef MPTSAS_GET_LED
-static int
-mptsas_get_led_status(mptsas_t *mpt, mptsas_target_t *ptgt,
-    uint32_t *slotstatus)
-{
-        return (mptsas_send_sep(mpt, ptgt, slotstatus,
-            MPI2_SEP_REQ_ACTION_READ_STATUS));
-}
-#endif
-static int
-mptsas_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t slotstatus)
-{
-        NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
-            slotstatus, ptgt->m_slot_num));
-        return (mptsas_send_sep(mpt, ptgt, &slotstatus,
-            MPI2_SEP_REQ_ACTION_WRITE_STATUS));
-}
-/*
- *  send sep request, use enclosure/slot addressing
- */
-static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
-    uint32_t *status, uint8_t act)
-{
-        Mpi2SepRequest_t        req;
-        Mpi2SepReply_t          rep;
-        int                     ret;
-
-        ASSERT(mutex_owned(&mpt->m_mutex));
-
-        bzero(&req, sizeof (req));
-        bzero(&rep, sizeof (rep));
-
-        /* Do nothing for RAID volumes */
-        if (ptgt->m_phymask == 0) {
-                NDBG14(("mptsas_send_sep: Skip RAID volumes"));
-                return (DDI_FAILURE);
-        }
-
-        req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
-        req.Action = act;
-        req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
-        req.EnclosureHandle = LE_16(ptgt->m_enclosure);
-        req.Slot = LE_16(ptgt->m_slot_num);
-        if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
-                req.SlotStatus = LE_32(*status);
-        }
-        ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
-            sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
-        if (ret != 0) {
-                mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
-                    "Processor Request message error %d", ret);
-                return (DDI_FAILURE);
-        }
-        /* do passthrough success, check the ioc status */
-        if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
-                if ((LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) ==
-                    MPI2_IOCSTATUS_INVALID_FIELD) {
-                        mptsas_log(mpt, CE_NOTE, "send sep act %x: Not "
-                            "supported action, loginfo %x", act,
-                            LE_32(rep.IOCLogInfo));
-                        return (DDI_FAILURE);
-                }
-                mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
-                    "status:%x", act, LE_16(rep.IOCStatus));
-                return (DDI_FAILURE);
-        }
-        if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
-                *status = LE_32(rep.SlotStatus);
-        }
-
-        return (DDI_SUCCESS);
-}
-
 int
 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
     ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
     uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
 {

@@ -16172,28 +15385,6 @@
 
         (void) ddi_dma_unbind_handle(*dma_hdp);
         (void) ddi_dma_mem_free(acc_hdp);
         ddi_dma_free_handle(dma_hdp);
         dma_hdp = NULL;
-}
-
-static int
-mptsas_outstanding_cmds_n(mptsas_t *mpt)
-{
-        int n = 0, i;
-        for (i = 0; i < mpt->m_slot_freeq_pair_n; i++) {
-                mutex_enter(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_allocq.s.m_fq_mutex);
-                mutex_enter(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_releq.s.m_fq_mutex);
-                n += (mpt->m_slot_freeq_pairp[i].m_slot_allocq.s.m_fq_n_init -
-                    mpt->m_slot_freeq_pairp[i].m_slot_allocq.s.m_fq_n -
-                    mpt->m_slot_freeq_pairp[i].m_slot_releq.s.m_fq_n);
-                mutex_exit(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_releq.s.m_fq_mutex);
-                mutex_exit(&mpt->m_slot_freeq_pairp[i].
-                    m_slot_allocq.s.m_fq_mutex);
-        }
-        if (mpt->m_max_requests - 2 < n)
-                panic("mptsas: free slot allocq and releq crazy");
-        return (n);
 }