Print this page
NEX-5717 import QLogic 16G FC drivers
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
        
*** 17,41 ****
   * information: Portions Copyright [yyyy] [name of copyright owner]
   *
   * CDDL HEADER END
   */
  
! /* Copyright 2010 QLogic Corporation */
  
  /*
!  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
   */
  
! #pragma ident   "Copyright 2010 QLogic Corporation; ql_isr.c"
  
  /*
   * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
   *
   * ***********************************************************************
   * *                                                                    **
   * *                            NOTICE                                  **
!  * *            COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION              **
   * *                    ALL RIGHTS RESERVED                             **
   * *                                                                    **
   * ***********************************************************************
   *
   */
--- 17,41 ----
   * information: Portions Copyright [yyyy] [name of copyright owner]
   *
   * CDDL HEADER END
   */
  
! /* Copyright 2015 QLogic Corporation */
  
  /*
!  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
   */
  
! #pragma ident   "Copyright 2015 QLogic Corporation; ql_isr.c"
  
  /*
   * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
   *
   * ***********************************************************************
   * *                                                                    **
   * *                            NOTICE                                  **
!  * *            COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION              **
   * *                    ALL RIGHTS RESERVED                             **
   * *                                                                    **
   * ***********************************************************************
   *
   */
*** 47,569 ****
  #include <ql_isr.h>
  #include <ql_init.h>
  #include <ql_mbx.h>
  #include <ql_nx.h>
  #include <ql_xioctl.h>
  
  /*
   * Local Function Prototypes.
   */
! static void ql_handle_uncommon_risc_intr(ql_adapter_state_t *, uint32_t,
!     uint32_t *);
! static void ql_spurious_intr(ql_adapter_state_t *, int);
! static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint32_t *,
!     uint32_t *, int);
! static void ql_async_event(ql_adapter_state_t *, uint32_t, ql_head_t *,
!     uint32_t *, uint32_t *, int);
! static void ql_fast_fcp_post(ql_srb_t *);
! static void ql_response_pkt(ql_adapter_state_t *, ql_head_t *, uint32_t *,
!     uint32_t *, int);
! static void ql_error_entry(ql_adapter_state_t *, response_t *, ql_head_t *,
!     uint32_t *, uint32_t *);
! static int ql_status_entry(ql_adapter_state_t *, sts_entry_t *, ql_head_t *,
!     uint32_t *, uint32_t *);
! static int ql_24xx_status_entry(ql_adapter_state_t *, sts_24xx_entry_t *,
!     ql_head_t *, uint32_t *, uint32_t *);
! static int ql_status_error(ql_adapter_state_t *, ql_srb_t *, sts_entry_t *,
!     ql_head_t *, uint32_t *, uint32_t *);
! static void ql_status_cont_entry(ql_adapter_state_t *, sts_cont_entry_t *,
!     ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ip_entry(ql_adapter_state_t *, ip_entry_t *, ql_head_t *,
!     uint32_t *, uint32_t *);
! static void ql_ip_rcv_entry(ql_adapter_state_t *, ip_rcv_entry_t *,
!     ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ip_rcv_cont_entry(ql_adapter_state_t *,
!     ip_rcv_cont_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ip_rcv_24xx_entry_t *,
!     ql_head_t *, uint32_t *, uint32_t *);
! static void ql_ms_entry(ql_adapter_state_t *, ms_entry_t *, ql_head_t *,
!     uint32_t *, uint32_t *);
! static void ql_report_id_entry(ql_adapter_state_t *, report_id_1_t *,
!     ql_head_t *, uint32_t *, uint32_t *);
! static void ql_els_passthru_entry(ql_adapter_state_t *,
!     els_passthru_entry_rsp_t *, ql_head_t *, uint32_t *, uint32_t *);
! static ql_srb_t *ql_verify_preprocessed_cmd(ql_adapter_state_t *, uint32_t *,
!     uint32_t *, uint32_t *);
! static void ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags);
  
  /*
!  * Spurious interrupt counter
   */
! uint32_t        ql_spurious_cnt = 4;
! uint32_t        ql_max_intr_loop = 16;
  
  /*
!  * ql_isr
!  *      Process all INTX intr types.
   *
   * Input:
!  *      arg1:   adapter state pointer.
   *
!  * Returns:
!  *      DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
! /* ARGSUSED */
! uint_t
! ql_isr(caddr_t arg1)
  {
!         return (ql_isr_aif(arg1, 0));
  }
  
  /*
!  * ql_isr_default
!  *      Process unknown/unvectored intr types
   *
   * Input:
   *      arg1:   adapter state pointer.
-  *      arg2:   interrupt vector.
   *
   * Returns:
   *      DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  uint_t
! ql_isr_default(caddr_t arg1, caddr_t arg2)
  {
!         ql_adapter_state_t      *ha = (void *)arg1;
! 
!         EL(ha, "isr_default called: idx=%x\n", arg2);
!         return (ql_isr_aif(arg1, arg2));
  }
  
  /*
   * ql_isr_aif
   *      Process mailbox and I/O command completions.
   *
   * Input:
   *      arg:    adapter state pointer.
!  *      intvec: interrupt vector.
   *
   * Returns:
   *      DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  uint_t
! ql_isr_aif(caddr_t arg, caddr_t intvec)
  {
!         uint16_t                mbx;
!         uint32_t                stat;
          ql_adapter_state_t      *ha = (void *)arg;
!         uint32_t                set_flags = 0;
!         uint32_t                reset_flags = 0;
          ql_head_t               isr_done_q = {NULL, NULL};
          uint_t                  rval = DDI_INTR_UNCLAIMED;
!         int                     spurious_intr = 0;
!         boolean_t               intr = B_FALSE, daemon = B_FALSE;
!         int                     intr_loop = 4;
!         boolean_t               clear_spurious = B_TRUE;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         QL_PM_LOCK(ha);
          if (ha->power_level != PM_LEVEL_D0) {
!                 /*
!                  * Looks like we are about to go down soon, exit early.
!                  */
!                 QL_PM_UNLOCK(ha);
!                 QL_PRINT_3(CE_CONT, "(%d): power down exit\n", ha->instance);
                  return (DDI_INTR_UNCLAIMED);
          }
!         ha->busy++;
          QL_PM_UNLOCK(ha);
  
          /* Acquire interrupt lock. */
!         INTR_LOCK(ha);
! 
!         if (CFG_IST(ha, CFG_CTRL_2200)) {
!                 while (RD16_IO_REG(ha, istatus) & RISC_INT) {
!                         /* Reset idle timer. */
!                         ha->idle_timer = 0;
!                         rval = DDI_INTR_CLAIMED;
!                         if (intr_loop) {
!                                 intr_loop--;
                          }
  
!                         /* Special Fast Post 2200. */
!                         stat = 0;
!                         if (ha->task_daemon_flags & FIRMWARE_LOADED &&
!                             ha->flags & ONLINE) {
!                                 ql_srb_t        *sp;
! 
!                                 mbx = RD16_IO_REG(ha, mailbox_out[23]);
! 
!                                 if ((mbx & 3) == MBX23_SCSI_COMPLETION) {
!                                         /* Release mailbox registers. */
!                                         WRT16_IO_REG(ha, semaphore, 0);
! 
!                                         if (intr_loop) {
!                                                 WRT16_IO_REG(ha, hccr,
!                                                     HC_CLR_RISC_INT);
                                          }
  
!                                         /* Get handle. */
!                                         mbx >>= 4;
!                                         stat = mbx & OSC_INDEX_MASK;
! 
!                                         /* Validate handle. */
!                                         sp = stat < MAX_OUTSTANDING_COMMANDS ?
!                                             ha->outstanding_cmds[stat] : NULL;
! 
!                                         if (sp != NULL && (sp->handle & 0xfff)
!                                             == mbx) {
!                                                 ha->outstanding_cmds[stat] =
!                                                     NULL;
!                                                 sp->handle = 0;
!                                                 sp->flags &=
!                                                     ~SRB_IN_TOKEN_ARRAY;
! 
!                                                 /* Set completed status. */
!                                                 sp->flags |= SRB_ISP_COMPLETED;
! 
!                                                 /* Set completion status */
!                                                 sp->pkt->pkt_reason =
!                                                     CS_COMPLETE;
! 
!                                                 ql_fast_fcp_post(sp);
!                                         } else if (mbx !=
!                                             (QL_FCA_BRAND & 0xfff)) {
!                                                 if (sp == NULL) {
!                                                         EL(ha, "unknown IOCB"
!                                                             " handle=%xh\n",
!                                                             mbx);
                                                  } else {
!                                                         EL(ha, "mismatch IOCB"
!                                                             " handle pkt=%xh, "
!                                                             "sp=%xh\n", mbx,
!                                                             sp->handle & 0xfff);
                                                  }
  
!                                                 (void) ql_binary_fw_dump(ha,
!                                                     FALSE);
! 
!                                                 if (!(ha->task_daemon_flags &
!                                                     (ISP_ABORT_NEEDED |
!                                                     ABORT_ISP_ACTIVE))) {
!                                                         EL(ha, "ISP Invalid "
!                                                             "handle, "
!                                                             "isp_abort_needed"
!                                                             "\n");
!                                                         set_flags |=
!                                                             ISP_ABORT_NEEDED;
                                                  }
-                                         }
-                                 }
-                         }
  
!                         if (stat == 0) {
!                                 /* Check for mailbox interrupt. */
!                                 mbx = RD16_IO_REG(ha, semaphore);
!                                 if (mbx & BIT_0) {
!                                         /* Release mailbox registers. */
!                                         WRT16_IO_REG(ha, semaphore, 0);
  
                                          /* Get mailbox data. */
                                          mbx = RD16_IO_REG(ha, mailbox_out[0]);
                                          if (mbx > 0x3fff && mbx < 0x8000) {
                                                  ql_mbx_completion(ha, mbx,
!                                                     &set_flags, &reset_flags,
!                                                     intr_loop);
!                                         } else if (mbx > 0x7fff &&
!                                             mbx < 0xc000) {
!                                                 ql_async_event(ha, mbx,
                                                      &isr_done_q, &set_flags,
!                                                     &reset_flags, intr_loop);
                                          } else {
!                                                 EL(ha, "UNKNOWN interrupt "
!                                                     "type\n");
!                                                 intr = B_TRUE;
                                          }
                                  } else {
!                                         ha->isp_rsp_index = RD16_IO_REG(ha,
!                                             resp_in);
! 
!                                         if (ha->isp_rsp_index !=
!                                             ha->rsp_ring_index) {
!                                                 ql_response_pkt(ha,
                                                      &isr_done_q, &set_flags,
!                                                     &reset_flags, intr_loop);
!                                         } else if (++spurious_intr ==
!                                             MAX_SPURIOUS_INTR) {
!                                                 /*
!                                                  * Process excessive
!                                                  * spurious intrrupts
!                                                  */
!                                                 ql_spurious_intr(ha,
!                                                     intr_loop);
!                                                 EL(ha, "excessive spurious "
!                                                     "interrupts, "
!                                                     "isp_abort_needed\n");
!                                                 set_flags |= ISP_ABORT_NEEDED;
                                          } else {
!                                                 intr = B_TRUE;
                                          }
                                  }
-                         }
- 
                          /* Clear RISC interrupt */
!                         if (intr || intr_loop == 0) {
!                                 intr = B_FALSE;
!                                 WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
                          }
- 
-                         if (set_flags != 0 || reset_flags != 0) {
-                                 TASK_DAEMON_LOCK(ha);
-                                 ha->task_daemon_flags |= set_flags;
-                                 ha->task_daemon_flags &= ~reset_flags;
-                                 TASK_DAEMON_UNLOCK(ha);
-                                 set_flags = 0;
-                                 reset_flags = 0;
-                                 daemon = B_TRUE;
-                         }
-                 }
          } else {
!                 uint32_t        ql_max_intr_loop_cnt = 0;
! 
!                 if (CFG_IST(ha, CFG_CTRL_8021)) {
                          ql_8021_clr_hw_intr(ha);
-                         intr_loop = 1;
                  }
-                 while (((stat = RD32_IO_REG(ha, risc2host)) & RH_RISC_INT) &&
-                     (++ql_max_intr_loop_cnt < ql_max_intr_loop)) {
  
!                         clear_spurious = B_TRUE;        /* assume ok */
  
                          /* Capture FW defined interrupt info */
                          mbx = MSW(stat);
  
!                         /* Reset idle timer. */
!                         ha->idle_timer = 0;
!                         rval = DDI_INTR_CLAIMED;
! 
!                         if (CFG_IST(ha, CFG_CTRL_8021) &&
!                             (RD32_IO_REG(ha, nx_risc_int) == 0 ||
!                             intr_loop == 0)) {
!                                 break;
                          }
  
-                         if (intr_loop) {
-                                 intr_loop--;
-                         }
- 
                          switch (stat & 0x1ff) {
                          case ROM_MBX_SUCCESS:
                          case ROM_MBX_ERR:
                                  ql_mbx_completion(ha, mbx, &set_flags,
!                                     &reset_flags, intr_loop);
! 
!                                 /* Release mailbox registers. */
!                                 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
!                                         WRT16_IO_REG(ha, semaphore, 0);
!                                 }
                                  break;
  
                          case MBX_SUCCESS:
                          case MBX_ERR:
-                                 /* Sun FW, Release mailbox registers. */
-                                 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
-                                         WRT16_IO_REG(ha, semaphore, 0);
-                                 }
                                  ql_mbx_completion(ha, mbx, &set_flags,
!                                     &reset_flags, intr_loop);
                                  break;
  
                          case ASYNC_EVENT:
!                                 /* Sun FW, Release mailbox registers. */
!                                 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
!                                         WRT16_IO_REG(ha, semaphore, 0);
!                                 }
!                                 ql_async_event(ha, (uint32_t)mbx, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case RESP_UPDATE:
!                                 if (mbx != ha->rsp_ring_index) {
!                                         ha->isp_rsp_index = mbx;
!                                         ql_response_pkt(ha, &isr_done_q,
!                                             &set_flags, &reset_flags,
!                                             intr_loop);
!                                 } else if (++spurious_intr ==
!                                     ql_spurious_cnt) {
!                                         /* Process excessive spurious intr. */
!                                         ql_spurious_intr(ha, intr_loop);
!                                         EL(ha, "excessive spurious "
!                                             "interrupts, isp_abort_needed\n");
!                                         set_flags |= ISP_ABORT_NEEDED;
!                                         clear_spurious = B_FALSE;
                                  } else {
!                                         QL_PRINT_10(CE_CONT, "(%d): response "
!                                             "ring index same as before\n",
!                                             ha->instance);
!                                         intr = B_TRUE;
!                                         clear_spurious = B_FALSE;
                                  }
                                  break;
  
                          case SCSI_FAST_POST_16:
                                  stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT;
!                                 ql_async_event(ha, stat, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case SCSI_FAST_POST_32:
                                  stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT;
!                                 ql_async_event(ha, stat, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case CTIO_FAST_POST:
                                  stat = (stat & 0xffff0000) |
                                      MBA_CTIO_COMPLETION;
!                                 ql_async_event(ha, stat, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case IP_FAST_POST_XMT:
                                  stat = (stat & 0xffff0000) | MBA_IP_COMPLETION;
!                                 ql_async_event(ha, stat, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case IP_FAST_POST_RCV:
                                  stat = (stat & 0xffff0000) | MBA_IP_RECEIVE;
!                                 ql_async_event(ha, stat, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case IP_FAST_POST_BRD:
                                  stat = (stat & 0xffff0000) | MBA_IP_BROADCAST;
!                                 ql_async_event(ha, stat, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case IP_FAST_POST_RCV_ALN:
                                  stat = (stat & 0xffff0000) |
                                      MBA_IP_HDR_DATA_SPLIT;
!                                 ql_async_event(ha, stat, &isr_done_q,
!                                     &set_flags, &reset_flags, intr_loop);
                                  break;
  
                          case ATIO_UPDATE:
                                  EL(ha, "unsupported ATIO queue update"
                                      " interrupt, status=%xh\n", stat);
-                                 intr = B_TRUE;
                                  break;
  
                          case ATIO_RESP_UPDATE:
                                  EL(ha, "unsupported ATIO response queue "
                                      "update interrupt, status=%xh\n", stat);
-                                 intr = B_TRUE;
                                  break;
  
                          default:
!                                 ql_handle_uncommon_risc_intr(ha, stat,
                                      &set_flags);
-                                 intr = B_TRUE;
                                  break;
                          }
  
                          /* Clear RISC interrupt */
!                         if (intr || intr_loop == 0) {
!                                 intr = B_FALSE;
!                                 if (CFG_IST(ha, CFG_CTRL_8021)) {
!                                         ql_8021_clr_fw_intr(ha);
!                                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
!                                         WRT32_IO_REG(ha, hccr,
!                                             HC24_CLR_RISC_INT);
!                                 } else {
!                                         WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
                                  }
-                         }
  
!                         if (set_flags != 0 || reset_flags != 0) {
!                                 TASK_DAEMON_LOCK(ha);
!                                 ha->task_daemon_flags |= set_flags;
!                                 ha->task_daemon_flags &= ~reset_flags;
!                                 TASK_DAEMON_UNLOCK(ha);
!                                 set_flags = 0;
!                                 reset_flags = 0;
!                                 daemon = B_TRUE;
                          }
- 
-                         if (ha->flags & PARITY_ERROR) {
-                                 EL(ha, "parity/pause exit\n");
-                                 mbx = RD16_IO_REG(ha, hccr); /* PCI posting */
-                                 break;
                          }
  
-                         if (clear_spurious) {
-                                 spurious_intr = 0;
-                         }
-                 }
-         }
- 
          /* Process claimed interrupts during polls. */
          if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) {
                  ha->intr_claimed = B_FALSE;
                  rval = DDI_INTR_CLAIMED;
          }
  
          /* Release interrupt lock. */
!         INTR_UNLOCK(ha);
  
!         if (daemon) {
!                 ql_awaken_task_daemon(ha, NULL, 0, 0);
          }
  
          if (isr_done_q.first != NULL) {
!                 ql_done(isr_done_q.first);
          }
  
          if (rval == DDI_INTR_CLAIMED) {
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
                  ha->xioctl->TotalInterrupts++;
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): interrupt not claimed\n",
!                     ha->instance);
          }
  
-         QL_PM_LOCK(ha);
-         ha->busy--;
-         QL_PM_UNLOCK(ha);
- 
          return (rval);
  }
  
  /*
   * ql_handle_uncommon_risc_intr
   *      Handle an uncommon RISC interrupt.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      stat:           interrupt status
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_handle_uncommon_risc_intr(ql_adapter_state_t *ha, uint32_t stat,
!     uint32_t *set_flags)
  {
          uint16_t        hccr_reg;
  
          hccr_reg = RD16_IO_REG(ha, hccr);
  
--- 47,589 ----
  #include <ql_isr.h>
  #include <ql_init.h>
  #include <ql_mbx.h>
  #include <ql_nx.h>
  #include <ql_xioctl.h>
+ #include <ql_fm.h>
  
  /*
   * Local Function Prototypes.
   */
! static void ql_clr_risc_intr(ql_adapter_state_t *);
! static void ql_handle_uncommon_risc_intr(ql_adapter_state_t *, int, uint32_t,
!     uint64_t *);
! static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint64_t *,
!     uint64_t *);
! static void ql_async_event(ql_adapter_state_t *, ql_response_q_t *, uint32_t,
!     ql_head_t *, uint64_t *, uint64_t *);
! static void ql_fast_fcp_post(ql_srb_t *, ql_response_q_t *);
! static void ql_response_pkt(ql_adapter_state_t *, ql_response_q_t *,
!     ql_head_t *, uint64_t *, uint64_t *);
! static void ql_error_entry(ql_adapter_state_t *, ql_response_q_t *,
!     response_t *, ql_head_t *, uint64_t *, uint64_t *);
! static int ql_status_entry(ql_adapter_state_t *, ql_response_q_t *,
!     sts_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static int ql_24xx_status_entry(ql_adapter_state_t *, ql_response_q_t *,
!     sts_24xx_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static int ql_status_error(ql_adapter_state_t *, ql_response_q_t *, ql_srb_t *,
!     sts_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_status_cont_entry(ql_adapter_state_t *, ql_response_q_t *,
!     sts_cont_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_entry(ql_adapter_state_t *, ql_response_q_t *, ip_entry_t *,
!     ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_rcv_entry(ql_adapter_state_t *, ql_response_q_t *,
!     ip_rcv_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_rcv_cont_entry(ql_adapter_state_t *, ql_response_q_t *,
!     ip_rcv_cont_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ql_response_q_t *,
!     ip_rcv_24xx_entry_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_ms_entry(ql_adapter_state_t *, ql_response_q_t *, ms_entry_t *,
!     ql_head_t *, uint64_t *, uint64_t *);
! static void ql_report_id_entry(ql_adapter_state_t *, ql_response_q_t *,
!     report_id_acq_t *, ql_head_t *, uint64_t *, uint64_t *);
! static void ql_els_passthru_entry(ql_adapter_state_t *, ql_response_q_t *,
!     els_passthru_entry_rsp_t *, ql_head_t *, uint64_t *, uint64_t *);
! static ql_srb_t *ql_verify_preprocessed_cmd(ql_adapter_state_t *,
!     ql_response_q_t *, uint32_t *, uint32_t *, uint64_t *, uint64_t *);
! static void ql_signal_abort(ql_adapter_state_t *, uint64_t *);
  
  /*
!  * ql_disable_intr
!  *      Disable interrupts.
!  *
!  * Input:
!  *      ha:     adapter state pointer.
!  *
!  * Context:
!  *      Interrupt or Kernel context, no mailbox commands allowed.
   */
! void
! ql_disable_intr(ql_adapter_state_t *ha)
! {
!         int     i, rval;
  
+         QL_PRINT_10(ha, "started\n");
+ 
+         if (CFG_IST(ha, CFG_CTRL_82XX)) {
+                 ql_8021_disable_intrs(ha);
+         } else {
+                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
+                         WRT32_IO_REG(ha, ictrl, 0);
+                         (void) RD32_IO_REG(ha, ictrl);  /* PCI posting */
+                 } else {
+                         WRT16_IO_REG(ha, ictrl, 0);
+                         (void) RD16_IO_REG(ha, ictrl);  /* PCI posting */
+                 }
+         }
+         if (ha->intr_cap & DDI_INTR_FLAG_MASKABLE) {
+                 for (i = 0; i < ha->intr_cnt; i++) {
+                         QL_PRINT_10(ha, "intr_set_mask %d\n", i);
+                         if ((rval = ddi_intr_set_mask(ha->htable[i])) !=
+                             DDI_SUCCESS) {
+                                 EL(ha, "intr_set_mask status=%xh\n", rval);
+                         }
+                 }
+         }
+         ADAPTER_STATE_LOCK(ha);
+         ha->flags &= ~INTERRUPTS_ENABLED;
+         ADAPTER_STATE_UNLOCK(ha);
+ 
+         QL_PRINT_10(ha, "done\n");
+ }
+ 
  /*
!  * ql_enaable_intr
!  *      Enable interrupts.
   *
   * Input:
!  *      ha:     adapter state pointer.
   *
!  * Context:
!  *      Interrupt or Kernel context, no mailbox commands allowed.
!  */
! void
! ql_enable_intr(ql_adapter_state_t *ha)
! {
!         int     i, rval;
! 
!         QL_PRINT_10(ha, "started\n");
! 
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                 ql_8021_enable_intrs(ha);
!         } else {
!                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
!                         WRT32_IO_REG(ha, ictrl, ISP_EN_RISC);
!                         (void) RD32_IO_REG(ha, ictrl);  /* PCI posting */
!                 } else {
!                         WRT16_IO_REG(ha, ictrl, ISP_EN_INT + ISP_EN_RISC);
!                         (void) RD16_IO_REG(ha, ictrl);  /* PCI posting */
!                 }
!         }
!         if (ha->intr_cap & DDI_INTR_FLAG_MASKABLE) {
!                 for (i = 0; i < ha->intr_cnt; i++) {
!                         QL_PRINT_10(ha, "intr_clr_mask %d\n", i);
!                         if ((rval = ddi_intr_clr_mask(ha->htable[i])) !=
!                             DDI_SUCCESS) {
!                                 EL(ha, "intr_clr_mask status=%xh\n", rval);
!                         }
!                 }
!         }
!         ADAPTER_STATE_LOCK(ha);
!         ha->flags |= INTERRUPTS_ENABLED;
!         ADAPTER_STATE_UNLOCK(ha);
! 
!         QL_PRINT_10(ha, "done\n");
! }
! 
! /*
!  * ql_clr_risc_intr
!  *      Clear firmware interrupt.
   *
+  * Input:
+  *      ha:     adapter state pointer.
+  *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
! static void
! ql_clr_risc_intr(ql_adapter_state_t *ha)
  {
!         QL_PRINT_3(ha, "started\n");
! 
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                 ql_8021_clr_fw_intr(ha);
!         } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
!                 WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
!                 RD32_IO_REG(ha, hccr);  /* PCI posting. */
!         } else {
!                 WRT16_IO_REG(ha, semaphore, 0);
!                 WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
!                 RD16_IO_REG(ha, hccr);  /* PCI posting. */
!         }
! 
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
!  * ql_isr
!  *      Process all INTX intr types.
   *
   * Input:
   *      arg1:   adapter state pointer.
   *
   * Returns:
   *      DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  uint_t
! ql_isr(caddr_t arg1)
  {
!         return (ql_isr_aif(arg1, 0));
  }
  
  /*
   * ql_isr_aif
   *      Process mailbox and I/O command completions.
   *
   * Input:
   *      arg:    adapter state pointer.
!  *      arg2:   interrupt vector.
   *
   * Returns:
   *      DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  uint_t
! ql_isr_aif(caddr_t arg, caddr_t arg2)
  {
!         uint32_t                mbx, stat;
          ql_adapter_state_t      *ha = (void *)arg;
!         uint64_t                set_flags = 0, reset_flags = 0;
          ql_head_t               isr_done_q = {NULL, NULL};
          uint_t                  rval = DDI_INTR_UNCLAIMED;
!         ql_response_q_t         *rsp_q = NULL;
!         int                     intr, index = (int)((uintptr_t)arg2);
  
!         QL_PRINT_3(ha, "started, index=%d\n", index);
  
!         /* Exit if not attached. */
!         if (ha == NULL || ha->intr_pri == NULL) {
!                 EL(ha, "ha=%p, intr_pri=%p not attached\n", (void *)ha,
!                     ha != NULL ? ha->intr_pri : NULL);
!                 return (DDI_INTR_UNCLAIMED);
!         }
! 
!         /* Exit if chip not powered up. */
          if (ha->power_level != PM_LEVEL_D0) {
!                 EL(ha, "power down exit\n");
                  return (DDI_INTR_UNCLAIMED);
          }
!         QL_PM_LOCK(ha);
!         ha->pm_busy++;
          QL_PM_UNLOCK(ha);
  
          /* Acquire interrupt lock. */
!         if (index > ha->rsp_queues_cnt) {
!                 intr = index = 0;
!         } else if (index) {
!                 intr = index - 1;
!         } else {
!                 intr = 0;
          }
+         INDX_INTR_LOCK(ha, intr);
  
!         if (index && ha->flags & NO_INTR_HANDSHAKE) {
!                 QL_PRINT_3(ha, "MULTI_Q_RSP_UPDATE, index=%xh\n", index);
!                 index--;
!                 if (index < ha->rsp_queues_cnt) {
!                         rsp_q = ha->rsp_queues[index];
                  }
+                 if (rsp_q == NULL) {
+                         EL(ha, "unsupported MULTI_Q_RSP_UPDATE, index=%d\n",
+                             index);
+                         rsp_q = ha->rsp_queues[0];
+                 }
  
!                 if (ha->flags & QUEUE_SHADOW_PTRS) {
!                         (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle,
!                             (off_t)rsp_q->rsp_in_shadow_ofst,
!                             SHADOW_ENTRY_SIZE, DDI_DMA_SYNC_FORCPU);
!                         mbx = ddi_get32(rsp_q->rsp_ring.acc_handle,
!                             rsp_q->rsp_in_shadow_ptr);
                  } else {
!                         mbx = RD32_MBAR_REG(ha, rsp_q->mbar_rsp_in);
                  }
  
!                 if (mbx != rsp_q->rsp_ring_index) {
!                         rsp_q->isp_rsp_index = (uint16_t)mbx;
!                         ql_response_pkt(ha, rsp_q, &isr_done_q,
!                             &set_flags, &reset_flags);
!                         /* PCI posting */
!                         (void) RD32_MBAR_REG(ha, rsp_q->mbar_rsp_in);
!                 } else if (ha->flags & INTERRUPTS_ENABLED) {
!                         /*EMPTY*/
!                         QL_PRINT_3(ha, "MULTI_Q_RSP_UPDATE mbar_rsp_in "
!                             "same as before\n");
                  }
  
!                 /* Set interrupt claimed status. */
!                 rval = DDI_INTR_CLAIMED;
  
+         } else if (CFG_IST(ha, CFG_CTRL_22XX)) {
+                 rsp_q = ha->rsp_queues[0];
+                 if (RD16_IO_REG(ha, istatus) & RISC_INT) {
+                         rval = DDI_INTR_CLAIMED;
+ 
+                         /* Check for mailbox interrupt. */
+                         stat = RD16_IO_REG(ha, semaphore);
+                         if (stat & BIT_0) {
                                  /* Get mailbox data. */
                                  mbx = RD16_IO_REG(ha, mailbox_out[0]);
                                  if (mbx > 0x3fff && mbx < 0x8000) {
                                          ql_mbx_completion(ha, mbx,
!                                             &set_flags, &reset_flags);
!                                 } else if (mbx > 0x7fff && mbx < 0xc000) {
!                                         ql_async_event(ha, rsp_q, mbx,
                                              &isr_done_q, &set_flags,
!                                             &reset_flags);
                                  } else {
!                                         EL(ha, "22XX unknown interrupt type\n");
                                  }
                          } else {
!                                 rsp_q->isp_rsp_index = RD16_IO_REG(ha, resp_in);
!                                 if (rsp_q->isp_rsp_index !=
!                                     rsp_q->rsp_ring_index) {
!                                         ql_response_pkt(ha, rsp_q,
                                              &isr_done_q, &set_flags,
!                                             &reset_flags);
                                  } else {
!                                         /*EMPTY*/
!                                         QL_PRINT_10(ha, "22XX isp_rsp_index "
!                                             "same as before\n");
                                  }
                          }
                          /* Clear RISC interrupt */
!                         ql_clr_risc_intr(ha);
                  }
          } else {
!                 if (CFG_IST(ha, CFG_CTRL_82XX)) {
                          ql_8021_clr_hw_intr(ha);
                  }
  
!                 if (((stat = RD32_IO_REG(ha, risc2host)) & RH_RISC_INT) == 0) {
!                         QL_PRINT_10(ha, "done, index=%d, no interrupt "
!                             "stat=%xh\n", index, stat);
!                         rval = DDI_INTR_UNCLAIMED;
!                 } else if (ha->ql_dump_state & QL_DUMPING) {
!                         EL(ha, "fw_dump, index=%d, active stat=%xh\n",
!                             index, stat);
!                         rval = DDI_INTR_CLAIMED;
!                 } else if (CFG_IST(ha, CFG_CTRL_82XX) &&
!                     RD32_IO_REG(ha, nx_risc_int) == 0) {
!                         QL_PRINT_10(ha, "done, index=%d, no nx_risc_int "
!                             "stat=%xh\n", index, stat);
!                         rval = DDI_INTR_UNCLAIMED;
!                 } else {
!                         rval = DDI_INTR_CLAIMED;
!                         QL_PRINT_3(ha, "index=%d, interrupt stat=%xh\n",
!                             index, stat);
  
                          /* Capture FW defined interrupt info */
                          mbx = MSW(stat);
  
!                         if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
!                             != DDI_FM_OK) {
!                                 qlc_fm_report_err_impact(ha,
!                                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
                          }
  
                          switch (stat & 0x1ff) {
                          case ROM_MBX_SUCCESS:
                          case ROM_MBX_ERR:
                                  ql_mbx_completion(ha, mbx, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case MBX_SUCCESS:
                          case MBX_ERR:
                                  ql_mbx_completion(ha, mbx, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case ASYNC_EVENT:
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     (uint32_t)mbx, &isr_done_q,
!                                     &set_flags, &reset_flags);
                                  break;
  
+                         case MULTI_Q_RSP_UPDATE:
+                                 QL_PRINT_3(ha, "MULTI_Q_RSP_UPDATE mbx=%xh\n",
+                                     mbx);
+                                 if (mbx < ha->rsp_queues_cnt) {
+                                         rsp_q = ha->rsp_queues[mbx];
+                                 }
+                                 if (rsp_q == NULL) {
+                                         EL(ha, "unsupported MULTI_Q_RSP_UPDATE"
+                                             " mbx=%d\n", mbx);
+                                         rsp_q = ha->rsp_queues[0];
+                                 }
+                                 if (ha->flags & QUEUE_SHADOW_PTRS) {
+                                         (void) ddi_dma_sync(
+                                             rsp_q->rsp_ring.dma_handle,
+                                             (off_t)rsp_q->rsp_in_shadow_ofst,
+                                             SHADOW_ENTRY_SIZE,
+                                             DDI_DMA_SYNC_FORCPU);
+                                         mbx = ddi_get32(
+                                             rsp_q->rsp_ring.acc_handle,
+                                             rsp_q->rsp_in_shadow_ptr);
+                                 } else {
+                                         mbx = RD32_MBAR_REG(ha,
+                                             rsp_q->mbar_rsp_in);
+                                 }
+                                 /* FALLTHRU */
+ 
                          case RESP_UPDATE:
!                                 /* Clear RISC interrupt */
!                                 ql_clr_risc_intr(ha);
! 
!                                 if (rsp_q == NULL) {
!                                         rsp_q = ha->rsp_queues[0];
!                                 }
!                                 if (mbx != rsp_q->rsp_ring_index) {
!                                         rsp_q->isp_rsp_index = (uint16_t)mbx;
!                                         ql_response_pkt(ha, rsp_q, &isr_done_q,
!                                             &set_flags, &reset_flags);
                                  } else {
!                                         /*EMPTY*/
!                                         QL_PRINT_3(ha, "response "
!                                             "ring index same as before\n");
                                  }
                                  break;
  
                          case SCSI_FAST_POST_16:
                                  stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT;
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     stat, &isr_done_q, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case SCSI_FAST_POST_32:
                                  stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT;
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     stat, &isr_done_q, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case CTIO_FAST_POST:
                                  stat = (stat & 0xffff0000) |
                                      MBA_CTIO_COMPLETION;
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     stat, &isr_done_q, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case IP_FAST_POST_XMT:
                                  stat = (stat & 0xffff0000) | MBA_IP_COMPLETION;
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     stat, &isr_done_q, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case IP_FAST_POST_RCV:
                                  stat = (stat & 0xffff0000) | MBA_IP_RECEIVE;
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     stat, &isr_done_q, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case IP_FAST_POST_BRD:
                                  stat = (stat & 0xffff0000) | MBA_IP_BROADCAST;
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     stat, &isr_done_q, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case IP_FAST_POST_RCV_ALN:
                                  stat = (stat & 0xffff0000) |
                                      MBA_IP_HDR_DATA_SPLIT;
!                                 ql_async_event(ha, ha->rsp_queues[0],
!                                     stat, &isr_done_q, &set_flags,
!                                     &reset_flags);
                                  break;
  
                          case ATIO_UPDATE:
                                  EL(ha, "unsupported ATIO queue update"
                                      " interrupt, status=%xh\n", stat);
                                  break;
  
                          case ATIO_RESP_UPDATE:
                                  EL(ha, "unsupported ATIO response queue "
                                      "update interrupt, status=%xh\n", stat);
                                  break;
  
                          default:
!                                 ql_handle_uncommon_risc_intr(ha, intr, stat,
                                      &set_flags);
                                  break;
                          }
+                 }
  
                  /* Clear RISC interrupt */
!                 if (rval == DDI_INTR_CLAIMED && rsp_q == NULL) {
!                         ql_clr_risc_intr(ha);
                  }
  
!                 /* A0 chip delay */
!                 if (CFG_IST(ha, CFG_CTRL_83XX) && ha->rev_id == 1 &&
!                     ha->iflags & (IFLG_INTR_LEGACY | IFLG_INTR_FIXED)) {
!                         drv_usecwait(4);
                  }
          }
  
          /* Process claimed interrupts during polls. */
          if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) {
                  ha->intr_claimed = B_FALSE;
                  rval = DDI_INTR_CLAIMED;
          }
  
          /* Release interrupt lock. */
!         INDX_INTR_UNLOCK(ha, intr);
  
!         if (set_flags || reset_flags) {
!                 ql_awaken_task_daemon(ha, NULL, set_flags, reset_flags);
          }
  
          if (isr_done_q.first != NULL) {
!                 ql_done(isr_done_q.first, B_FALSE);
          }
  
+         QL_PM_LOCK(ha);
+         if (ha->pm_busy) {
+                 ha->pm_busy--;
+         }
+         QL_PM_UNLOCK(ha);
+ 
          if (rval == DDI_INTR_CLAIMED) {
!                 QL_PRINT_3(ha, "done\n");
!                 ha->idle_timer = 0;
                  ha->xioctl->TotalInterrupts++;
          } else {
                  /*EMPTY*/
!                 QL_PRINT_10(ha, "interrupt not claimed\n");
          }
  
          return (rval);
  }
  
  /*
   * ql_handle_uncommon_risc_intr
   *      Handle an uncommon RISC interrupt.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      intr:           interrupt index.
   *      stat:           interrupt status
+  *      set_flags:      task daemon flags to set.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_handle_uncommon_risc_intr(ql_adapter_state_t *ha, int intr, uint32_t stat,
!     uint64_t *set_flags)
  {
          uint16_t        hccr_reg;
  
          hccr_reg = RD16_IO_REG(ha, hccr);
  
*** 585,597 ****
--- 605,619 ----
                          ha->parity_stat_err = stat;
                  }
  
                  EL(ha, "parity/pause error, isp_abort_needed\n");
  
+                 INDX_INTR_UNLOCK(ha, intr);
                  if (ql_binary_fw_dump(ha, FALSE) != QL_SUCCESS) {
                          ql_reset_chip(ha);
                  }
+                 INDX_INTR_LOCK(ha, intr);
  
                  if (ha->parity_pause_errors == 0) {
                          ha->log_parity_pause = B_TRUE;
                  }
  
*** 600,686 ****
                  }
  
                  *set_flags |= ISP_ABORT_NEEDED;
  
                  /* Disable ISP interrupts. */
!                 CFG_IST(ha, CFG_CTRL_8021) ? ql_8021_disable_intrs(ha) :
!                     WRT16_IO_REG(ha, ictrl, 0);
!                 ADAPTER_STATE_LOCK(ha);
!                 ha->flags &= ~INTERRUPTS_ENABLED;
!                 ADAPTER_STATE_UNLOCK(ha);
          } else {
                  EL(ha, "UNKNOWN interrupt status=%xh, hccr=%xh\n",
                      stat, hccr_reg);
          }
  }
  
  /*
-  * ql_spurious_intr
-  *      Inform Solaris of spurious interrupts.
-  *
-  * Input:
-  *      ha:             adapter state pointer.
-  *      intr_clr:       early interrupt clear
-  *
-  * Context:
-  *      Interrupt or Kernel context, no mailbox commands allowed.
-  */
- static void
- ql_spurious_intr(ql_adapter_state_t *ha, int intr_clr)
- {
-         ddi_devstate_t  state;
- 
-         EL(ha, "Spurious interrupt\n");
- 
-         /* Disable ISP interrupts. */
-         WRT16_IO_REG(ha, ictrl, 0);
-         ADAPTER_STATE_LOCK(ha);
-         ha->flags &= ~INTERRUPTS_ENABLED;
-         ADAPTER_STATE_UNLOCK(ha);
- 
-         /* Clear RISC interrupt */
-         if (intr_clr) {
-                 if (CFG_IST(ha, CFG_CTRL_8021)) {
-                         ql_8021_clr_fw_intr(ha);
-                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
-                         WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
-                 } else {
-                         WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
-                 }
-         }
- 
-         state = ddi_get_devstate(ha->dip);
-         if (state == DDI_DEVSTATE_UP) {
-                 /*EMPTY*/
-                 ddi_dev_report_fault(ha->dip, DDI_SERVICE_DEGRADED,
-                     DDI_DEVICE_FAULT, "spurious interrupts");
-         }
- }
- 
- /*
   * ql_mbx_completion
   *      Processes mailbox completions.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      mb0:            Mailbox 0 contents.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
-  *      intr_clr:       early interrupt clear
   *
   * Context:
   *      Interrupt context.
   */
  /* ARGSUSED */
  static void
! ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint32_t *set_flags,
!     uint32_t *reset_flags, int intr_clr)
  {
          uint32_t        index;
          uint16_t        cnt;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Load return mailbox registers. */
          MBX_REGISTER_LOCK(ha);
  
          if (ha->mcp != NULL) {
--- 622,660 ----
                  }
  
                  *set_flags |= ISP_ABORT_NEEDED;
  
                  /* Disable ISP interrupts. */
!                 ql_disable_intr(ha);
          } else {
                  EL(ha, "UNKNOWN interrupt status=%xh, hccr=%xh\n",
                      stat, hccr_reg);
          }
  }
  
  /*
   * ql_mbx_completion
   *      Processes mailbox completions.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      mb0:            Mailbox 0 contents.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
   * Context:
   *      Interrupt context.
   */
  /* ARGSUSED */
  static void
! ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          uint32_t        index;
          uint16_t        cnt;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Load return mailbox registers. */
          MBX_REGISTER_LOCK(ha);
  
          if (ha->mcp != NULL) {
*** 697,783 ****
  
          } else {
                  EL(ha, "mcp == NULL\n");
          }
  
-         if (intr_clr) {
-                 /* Clear RISC interrupt. */
-                 if (CFG_IST(ha, CFG_CTRL_8021)) {
-                         ql_8021_clr_fw_intr(ha);
-                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
-                         WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
-                 } else {
-                         WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
-                 }
-         }
- 
          ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT);
          if (ha->flags & INTERRUPTS_ENABLED) {
                  cv_broadcast(&ha->cv_mbx_intr);
          }
  
          MBX_REGISTER_UNLOCK(ha);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_async_event
   *      Processes asynchronous events.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      mbx:            Mailbox 0 register.
   *      done_q:         head pointer to done queue.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
-  *      intr_clr:       early interrupt clear
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_async_event(ql_adapter_state_t *ha, uint32_t mbx, ql_head_t *done_q,
!     uint32_t *set_flags, uint32_t *reset_flags, int intr_clr)
  {
!         uint32_t                handle;
!         uint32_t                index;
!         uint16_t                cnt;
!         uint16_t                mb[MAX_MBOX_COUNT];
          ql_srb_t                *sp;
          port_id_t               s_id;
          ql_tgt_t                *tq;
-         boolean_t               intr = B_TRUE;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Setup to process fast completion. */
          mb[0] = LSW(mbx);
          switch (mb[0]) {
          case MBA_SCSI_COMPLETION:
!                 handle = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox_out[1]),
                      RD16_IO_REG(ha, mailbox_out[2]));
                  break;
  
          case MBA_CMPLT_1_16BIT:
!                 handle = MSW(mbx);
                  mb[0] = MBA_SCSI_COMPLETION;
                  break;
  
          case MBA_CMPLT_1_32BIT:
!                 handle = SHORT_TO_LONG(MSW(mbx),
                      RD16_IO_REG(ha, mailbox_out[2]));
                  mb[0] = MBA_SCSI_COMPLETION;
                  break;
  
          case MBA_CTIO_COMPLETION:
          case MBA_IP_COMPLETION:
!                 handle = CFG_IST(ha, CFG_CTRL_2200) ? SHORT_TO_LONG(
                      RD16_IO_REG(ha, mailbox_out[1]),
                      RD16_IO_REG(ha, mailbox_out[2])) :
                      SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox_out[2]));
                  mb[0] = MBA_SCSI_COMPLETION;
                  break;
  
          default:
                  break;
--- 671,792 ----
  
          } else {
                  EL(ha, "mcp == NULL\n");
          }
  
          ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT);
          if (ha->flags & INTERRUPTS_ENABLED) {
                  cv_broadcast(&ha->cv_mbx_intr);
          }
  
          MBX_REGISTER_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_async_event
   *      Processes asynchronous events.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      mbx:            Mailbox 0 register.
   *      done_q:         head pointer to done queue.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_async_event(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, uint32_t mbx,
!     ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
  {
!         uint32_t                index, handles[5];
!         uint16_t                cnt, handle_cnt, mb[MAX_MBOX_COUNT];
          ql_srb_t                *sp;
          port_id_t               s_id;
          ql_tgt_t                *tq;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Setup to process fast completion. */
          mb[0] = LSW(mbx);
          switch (mb[0]) {
          case MBA_SCSI_COMPLETION:
!                 handles[0] = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox_out[1]),
                      RD16_IO_REG(ha, mailbox_out[2]));
+                 handle_cnt = 1;
                  break;
  
          case MBA_CMPLT_1_16BIT:
!                 handles[0] = MSW(mbx);
!                 handle_cnt = 1;
                  mb[0] = MBA_SCSI_COMPLETION;
                  break;
  
+         case MBA_CMPLT_2_16BIT:
+                 handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+                 handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+                 handle_cnt = 2;
+                 mb[0] = MBA_SCSI_COMPLETION;
+                 break;
+ 
+         case MBA_CMPLT_3_16BIT:
+                 handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+                 handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+                 handles[2] = (uint32_t)RD16_IO_REG(ha, mailbox_out[3]);
+                 handle_cnt = 3;
+                 mb[0] = MBA_SCSI_COMPLETION;
+                 break;
+ 
+         case MBA_CMPLT_4_16BIT:
+                 handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+                 handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+                 handles[2] = (uint32_t)RD16_IO_REG(ha, mailbox_out[3]);
+                 handles[3] = (uint32_t)RD16_IO_REG(ha, mailbox_out[6]);
+                 handle_cnt = 4;
+                 mb[0] = MBA_SCSI_COMPLETION;
+                 break;
+ 
+         case MBA_CMPLT_5_16BIT:
+                 handles[0] = (uint32_t)RD16_IO_REG(ha, mailbox_out[1]);
+                 handles[1] = (uint32_t)RD16_IO_REG(ha, mailbox_out[2]);
+                 handles[2] = (uint32_t)RD16_IO_REG(ha, mailbox_out[3]);
+                 handles[3] = (uint32_t)RD16_IO_REG(ha, mailbox_out[6]);
+                 handles[4] = (uint32_t)RD16_IO_REG(ha, mailbox_out[7]);
+                 handle_cnt = 5;
+                 mb[0] = MBA_SCSI_COMPLETION;
+                 break;
+ 
          case MBA_CMPLT_1_32BIT:
!                 handles[0] = SHORT_TO_LONG(MSW(mbx),
                      RD16_IO_REG(ha, mailbox_out[2]));
+                 handle_cnt = 1;
                  mb[0] = MBA_SCSI_COMPLETION;
                  break;
  
+         case MBA_CMPLT_2_32BIT:
+                 handles[0] = SHORT_TO_LONG(
+                     RD16_IO_REG(ha, mailbox_out[1]),
+                     RD16_IO_REG(ha, mailbox_out[2]));
+                 handles[1] = SHORT_TO_LONG(
+                     RD16_IO_REG(ha, mailbox_out[6]),
+                     RD16_IO_REG(ha, mailbox_out[7]));
+                 handle_cnt = 2;
+                 mb[0] = MBA_SCSI_COMPLETION;
+                 break;
+ 
          case MBA_CTIO_COMPLETION:
          case MBA_IP_COMPLETION:
!                 handles[0] = CFG_IST(ha, CFG_CTRL_22XX) ? SHORT_TO_LONG(
                      RD16_IO_REG(ha, mailbox_out[1]),
                      RD16_IO_REG(ha, mailbox_out[2])) :
                      SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox_out[2]));
+                 handle_cnt = 1;
                  mb[0] = MBA_SCSI_COMPLETION;
                  break;
  
          default:
                  break;
*** 784,821 ****
          }
  
          /* Handle asynchronous event */
          switch (mb[0]) {
          case MBA_SCSI_COMPLETION:
!                 QL_PRINT_5(CE_CONT, "(%d): Fast post completion\n",
!                     ha->instance);
  
-                 if (intr_clr) {
-                         /* Clear RISC interrupt */
-                         if (CFG_IST(ha, CFG_CTRL_8021)) {
-                                 ql_8021_clr_fw_intr(ha);
-                         } else if (CFG_IST(ha, CFG_CTRL_242581)) {
-                                 WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
-                         } else {
-                                 WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
-                         }
-                         intr = B_FALSE;
-                 }
- 
                  if ((ha->flags & ONLINE) == 0) {
                          break;
                  }
  
                  /* Get handle. */
!                 index = handle & OSC_INDEX_MASK;
  
                  /* Validate handle. */
!                 sp = index < MAX_OUTSTANDING_COMMANDS ?
                      ha->outstanding_cmds[index] : NULL;
  
!                 if (sp != NULL && sp->handle == handle) {
                          ha->outstanding_cmds[index] = NULL;
                          sp->handle = 0;
                          sp->flags &= ~SRB_IN_TOKEN_ARRAY;
  
                          /* Set completed status. */
                          sp->flags |= SRB_ISP_COMPLETED;
--- 793,827 ----
          }
  
          /* Handle asynchronous event */
          switch (mb[0]) {
          case MBA_SCSI_COMPLETION:
!                 QL_PRINT_5(ha, "Fast post completion\n");
  
                  if ((ha->flags & ONLINE) == 0) {
                          break;
                  }
  
+                 for (cnt = 0; cnt < handle_cnt; cnt++) {
+                         QL_PRINT_5(ha, "Fast post completion, handle=%xh\n",
+                             handles[cnt]);
+ 
                          /* Get handle. */
!                         index = handles[cnt] & OSC_INDEX_MASK;
  
                          /* Validate handle. */
!                         sp = index < ha->osc_max_cnt ?
                              ha->outstanding_cmds[index] : NULL;
  
!                         if (sp == QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "QL_ABORTED_SRB handle=%xh\n",
!                                     handles[cnt]);
                                  ha->outstanding_cmds[index] = NULL;
+                                 continue;
+                         }
+                         if (sp != NULL && sp->handle == handles[cnt]) {
+                                 ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
  
                                  /* Set completed status. */
                                  sp->flags |= SRB_ISP_COMPLETED;
*** 825,867 ****
  
                          if (!(sp->flags & SRB_FCP_CMD_PKT)) {
                                  /* Place block on done queue */
                                  ql_add_link_b(done_q, &sp->cmd);
                          } else {
!                                 ql_fast_fcp_post(sp);
                          }
!                 } else if (handle != QL_FCA_BRAND) {
                          if (sp == NULL) {
                                  EL(ha, "%xh unknown IOCB handle=%xh\n",
!                                     mb[0], handle);
                          } else {
!                                 EL(ha, "%xh mismatch IOCB handle pkt=%xh, "
!                                     "sp=%xh\n", mb[0], handle, sp->handle);
                          }
  
!                         EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, mbx3=%xh,"
!                             "mbx6=%xh, mbx7=%xh\n", mb[0],
                              RD16_IO_REG(ha, mailbox_out[1]),
                              RD16_IO_REG(ha, mailbox_out[2]),
                              RD16_IO_REG(ha, mailbox_out[3]),
                              RD16_IO_REG(ha, mailbox_out[6]),
                              RD16_IO_REG(ha, mailbox_out[7]));
  
!                         (void) ql_binary_fw_dump(ha, FALSE);
  
                          if (!(ha->task_daemon_flags &
!                             (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
                                  EL(ha, "%xh ISP Invalid handle, "
                                      "isp_abort_needed\n", mb[0]);
                                  *set_flags |= ISP_ABORT_NEEDED;
                          }
                  }
                  break;
  
          case MBA_RESET:         /* Reset */
                  EL(ha, "%xh Reset received\n", mb[0]);
!                 *set_flags |= RESET_MARKER_NEEDED;
                  break;
  
          case MBA_SYSTEM_ERR:            /* System Error */
                  mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
                  mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
--- 831,877 ----
  
                                  if (!(sp->flags & SRB_FCP_CMD_PKT)) {
                                          /* Place block on done queue */
                                          ql_add_link_b(done_q, &sp->cmd);
                                  } else {
!                                         ql_fast_fcp_post(sp, rsp_q);
                                  }
!                         } else if (handles[cnt] != QL_FCA_BRAND) {
                                  if (sp == NULL) {
                                          EL(ha, "%xh unknown IOCB handle=%xh\n",
!                                             mb[0], handles[cnt]);
                                  } else {
!                                         EL(ha, "%xh mismatch IOCB handle "
!                                             "pkt=%xh, sp=%xh\n", mb[0],
!                                             handles[cnt], sp->handle);
                                  }
  
!                                 EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, "
!                                     "mbx3=%xh, mbx6=%xh, mbx7=%xh\n", mb[0],
                                      RD16_IO_REG(ha, mailbox_out[1]),
                                      RD16_IO_REG(ha, mailbox_out[2]),
                                      RD16_IO_REG(ha, mailbox_out[3]),
                                      RD16_IO_REG(ha, mailbox_out[6]),
                                      RD16_IO_REG(ha, mailbox_out[7]));
  
!                                 ADAPTER_STATE_LOCK(ha);
!                                 ha->flags |= FW_DUMP_NEEDED;
!                                 ADAPTER_STATE_UNLOCK(ha);
  
                                  if (!(ha->task_daemon_flags &
!                                     ISP_ABORT_NEEDED)) {
                                          EL(ha, "%xh ISP Invalid handle, "
                                              "isp_abort_needed\n", mb[0]);
                                          *set_flags |= ISP_ABORT_NEEDED;
                                  }
                          }
+                 }
                  break;
  
          case MBA_RESET:         /* Reset */
                  EL(ha, "%xh Reset received\n", mb[0]);
!                 *set_flags |= MARKER_NEEDED;
                  break;
  
          case MBA_SYSTEM_ERR:            /* System Error */
                  mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
                  mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
*** 908,921 ****
                              RD16_IO_REG(ha, mailbox_out[29]),
                              RD16_IO_REG(ha, mailbox_out[30]),
                              RD16_IO_REG(ha, mailbox_out[31]));
                  }
  
!                 (void) ql_binary_fw_dump(ha, FALSE);
  
!                 (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8002, mb[1],
!                     mb[2], mb[3]);
  
                  if (CFG_IST(ha, CFG_CTRL_81XX) && mb[7] & SE_MPI_RISC) {
                          ADAPTER_STATE_LOCK(ha);
                          ha->flags |= MPI_RESET_NEEDED;
                          ADAPTER_STATE_UNLOCK(ha);
--- 918,938 ----
                              RD16_IO_REG(ha, mailbox_out[29]),
                              RD16_IO_REG(ha, mailbox_out[30]),
                              RD16_IO_REG(ha, mailbox_out[31]));
                  }
  
!                 ADAPTER_STATE_LOCK(ha);
!                 ha->flags |= FW_DUMP_NEEDED;
!                 ADAPTER_STATE_UNLOCK(ha);
  
!                 /* Signal task daemon to store error log. */
!                 if (ha->errlog[0] == 0) {
!                         ha->errlog[3] = mb[3];
!                         ha->errlog[2] = mb[2];
!                         ha->errlog[1] = mb[1];
!                         ha->errlog[0] = FLASH_ERRLOG_AEN_8002;
!                 }
  
                  if (CFG_IST(ha, CFG_CTRL_81XX) && mb[7] & SE_MPI_RISC) {
                          ADAPTER_STATE_LOCK(ha);
                          ha->flags |= MPI_RESET_NEEDED;
                          ADAPTER_STATE_UNLOCK(ha);
*** 927,961 ****
  
          case MBA_REQ_TRANSFER_ERR:  /* Request Transfer Error */
                  EL(ha, "%xh Request Transfer Error received, "
                      "isp_abort_needed\n", mb[0]);
  
!                 (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8003,
!                     RD16_IO_REG(ha, mailbox_out[1]),
!                     RD16_IO_REG(ha, mailbox_out[2]),
!                     RD16_IO_REG(ha, mailbox_out[3]));
  
                  *set_flags |= ISP_ABORT_NEEDED;
                  ha->xioctl->ControllerErrorCount++;
                  break;
  
          case MBA_RSP_TRANSFER_ERR:  /* Response Xfer Err */
                  EL(ha, "%xh Response Transfer Error received,"
                      " isp_abort_needed\n", mb[0]);
  
!                 (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8004,
!                     RD16_IO_REG(ha, mailbox_out[1]),
!                     RD16_IO_REG(ha, mailbox_out[2]),
!                     RD16_IO_REG(ha, mailbox_out[3]));
  
                  *set_flags |= ISP_ABORT_NEEDED;
                  ha->xioctl->ControllerErrorCount++;
                  break;
  
          case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
!                 EL(ha, "%xh Request Queue Wake-up received\n",
!                     mb[0]);
                  break;
  
          case MBA_MENLO_ALERT:   /* Menlo Alert Notification */
                  mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
                  mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
--- 944,993 ----
  
          case MBA_REQ_TRANSFER_ERR:  /* Request Transfer Error */
                  EL(ha, "%xh Request Transfer Error received, "
                      "isp_abort_needed\n", mb[0]);
  
!                 /* Signal task daemon to store error log. */
!                 if (ha->errlog[0] == 0) {
!                         ha->errlog[3] = RD16_IO_REG(ha, mailbox_out[3]);
!                         ha->errlog[2] = RD16_IO_REG(ha, mailbox_out[2]);
!                         ha->errlog[1] = RD16_IO_REG(ha, mailbox_out[1]);
!                         ha->errlog[0] = FLASH_ERRLOG_AEN_8003;
!                 }
  
                  *set_flags |= ISP_ABORT_NEEDED;
                  ha->xioctl->ControllerErrorCount++;
+ 
+                 (void) qlc_fm_report_err_impact(ha,
+                     QL_FM_EREPORT_MBA_REQ_TRANSFER_ERR);
+ 
                  break;
  
          case MBA_RSP_TRANSFER_ERR:  /* Response Xfer Err */
                  EL(ha, "%xh Response Transfer Error received,"
                      " isp_abort_needed\n", mb[0]);
  
!                 /* Signal task daemon to store error log. */
!                 if (ha->errlog[0] == 0) {
!                         ha->errlog[3] = RD16_IO_REG(ha, mailbox_out[3]);
!                         ha->errlog[2] = RD16_IO_REG(ha, mailbox_out[2]);
!                         ha->errlog[1] = RD16_IO_REG(ha, mailbox_out[1]);
!                         ha->errlog[0] = FLASH_ERRLOG_AEN_8004;
!                 }
  
                  *set_flags |= ISP_ABORT_NEEDED;
                  ha->xioctl->ControllerErrorCount++;
+ 
+                 (void) qlc_fm_report_err_impact(ha,
+                     QL_FM_EREPORT_MBA_RSP_TRANSFER_ERR);
+ 
                  break;
  
          case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
!                 EL(ha, "%xh Request Queue Wake-up "
!                     "received, mbx1=%xh\n", mb[0],
!                     RD16_IO_REG(ha, mailbox_out[1]));
                  break;
  
          case MBA_MENLO_ALERT:   /* Menlo Alert Notification */
                  mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
                  mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
*** 980,990 ****
                  break;
  
          case MBA_LIP_F8:        /* Received a LIP F8. */
          case MBA_LIP_RESET:     /* LIP reset occurred. */
          case MBA_LIP_OCCURRED:  /* Loop Initialization Procedure */
!                 if (CFG_IST(ha, CFG_CTRL_8081)) {
                          EL(ha, "%xh DCBX_STARTED received, mbx1=%xh, mbx2=%xh"
                              "\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
                              RD16_IO_REG(ha, mailbox_out[2]));
                  } else {
                          EL(ha, "%xh LIP received\n", mb[0]);
--- 1012,1022 ----
                  break;
  
          case MBA_LIP_F8:        /* Received a LIP F8. */
          case MBA_LIP_RESET:     /* LIP reset occurred. */
          case MBA_LIP_OCCURRED:  /* Loop Initialization Procedure */
!                 if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
                          EL(ha, "%xh DCBX_STARTED received, mbx1=%xh, mbx2=%xh"
                              "\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
                              RD16_IO_REG(ha, mailbox_out[2]));
                  } else {
                          EL(ha, "%xh LIP received\n", mb[0]);
*** 1012,1023 ****
                          ql_enqueue_aen(ha, mb[0], NULL);
                  }
                  break;
  
          case MBA_LOOP_UP:
!                 if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322 |
!                     CFG_CTRL_24258081))) {
                          ha->iidma_rate = RD16_IO_REG(ha, mailbox_out[1]);
                          if (ha->iidma_rate == IIDMA_RATE_1GB) {
                                  ha->state = FC_PORT_STATE_MASK(
                                      ha->state) | FC_STATE_1GBIT_SPEED;
                                  index = 1;
--- 1044,1054 ----
                          ql_enqueue_aen(ha, mb[0], NULL);
                  }
                  break;
  
          case MBA_LOOP_UP:
!                 if (!CFG_IST(ha, CFG_CTRL_22XX)) {
                          ha->iidma_rate = RD16_IO_REG(ha, mailbox_out[1]);
                          if (ha->iidma_rate == IIDMA_RATE_1GB) {
                                  ha->state = FC_PORT_STATE_MASK(
                                      ha->state) | FC_STATE_1GBIT_SPEED;
                                  index = 1;
*** 1035,1044 ****
--- 1066,1083 ----
                                  index = 8;
                          } else if (ha->iidma_rate == IIDMA_RATE_10GB) {
                                  ha->state = FC_PORT_STATE_MASK(
                                      ha->state) | FC_STATE_10GBIT_SPEED;
                                  index = 10;
+                         } else if (ha->iidma_rate == IIDMA_RATE_16GB) {
+                                 ha->state = FC_PORT_STATE_MASK(
+                                     ha->state) | FC_STATE_16GBIT_SPEED;
+                                 index = 16;
+                         } else if (ha->iidma_rate == IIDMA_RATE_32GB) {
+                                 ha->state = FC_PORT_STATE_MASK(
+                                     ha->state) | FC_STATE_32GBIT_SPEED;
+                                 index = 32;
                          } else {
                                  ha->state = FC_PORT_STATE_MASK(
                                      ha->state);
                                  index = 0;
                          }
*** 1076,1086 ****
  
                  if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
                          ha->loop_down_timer = LOOP_DOWN_TIMER_START;
                  }
  
!                 if (CFG_IST(ha, CFG_CTRL_258081)) {
                          ha->sfp_stat = RD16_IO_REG(ha, mailbox_out[2]);
                  }
  
                  /* Update AEN queue. */
                  if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
--- 1115,1125 ----
  
                  if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
                          ha->loop_down_timer = LOOP_DOWN_TIMER_START;
                  }
  
!                 if (CFG_IST(ha, CFG_CTRL_252780818283)) {
                          ha->sfp_stat = RD16_IO_REG(ha, mailbox_out[2]);
                  }
  
                  /* Update AEN queue. */
                  if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
*** 1102,1121 ****
                  }
                  if (vha == NULL) {
                          break;
                  }
  
!                 if (CFG_IST(ha, CFG_CTRL_8081) && mb[1] == 0xffff &&
                      mb[2] == 7 && (MSB(mb[3]) == 0xe || MSB(mb[3]) == 0x1a ||
                      MSB(mb[3]) == 0x1c || MSB(mb[3]) == 0x1d ||
                      MSB(mb[3]) == 0x1e)) {
                          /*
                           * received FLOGI reject
                           * received FLOGO
                           * FCF configuration changed
                           * FIP Clear Virtual Link received
!                          * FKA timeout
                           */
                          if (!(ha->task_daemon_flags & LOOP_DOWN)) {
                                  *set_flags |= LOOP_DOWN;
                          }
                          ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE |
--- 1141,1163 ----
                  }
                  if (vha == NULL) {
                          break;
                  }
  
!                 if (mb[1] == 0xffff &&
                      mb[2] == 7 && (MSB(mb[3]) == 0xe || MSB(mb[3]) == 0x1a ||
                      MSB(mb[3]) == 0x1c || MSB(mb[3]) == 0x1d ||
                      MSB(mb[3]) == 0x1e)) {
+                         EL(ha, "%xh Port Database Update, Loop down "
+                             "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
+                             mb[0], mb[1], mb[2], mb[3]);
                          /*
                           * received FLOGI reject
                           * received FLOGO
                           * FCF configuration changed
                           * FIP Clear Virtual Link received
!                          * FCF timeout
                           */
                          if (!(ha->task_daemon_flags & LOOP_DOWN)) {
                                  *set_flags |= LOOP_DOWN;
                          }
                          ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE |
*** 1128,1139 ****
                   * database entry at loop_id 0x7fe which we use to
                   * acquire the Ports WWPN.
                   */
                  } else if ((mb[1] != 0x7fe) &&
                      ((FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE ||
!                     (CFG_IST(ha, CFG_CTRL_24258081) &&
!                     (mb[1] != 0xffff || mb[2] != 6 || mb[3] != 0))))) {
                          EL(ha, "%xh Port Database Update, Login/Logout "
                              "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
                              mb[0], mb[1], mb[2], mb[3]);
                  } else {
                          EL(ha, "%xh Port Database Update received, mbx1=%xh,"
--- 1170,1181 ----
                   * database entry at loop_id 0x7fe which we use to
                   * acquire the Ports WWPN.
                   */
                  } else if ((mb[1] != 0x7fe) &&
                      ((FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE ||
!                     (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
!                     (mb[2] != 6 || mb[3] != 0))))) {
                          EL(ha, "%xh Port Database Update, Login/Logout "
                              "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
                              mb[0], mb[1], mb[2], mb[3]);
                  } else {
                          EL(ha, "%xh Port Database Update received, mbx1=%xh,"
*** 1221,1231 ****
                  if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
                          EL(ha, "Unknown IP device=%xh\n", s_id.b24);
                          break;
                  }
  
!                 cnt = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
                      CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0],
                      ha->ip_init_ctrl_blk.cb24.buf_size[1]) :
                      CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0],
                      ha->ip_init_ctrl_blk.cb.buf_size[1]));
  
--- 1263,1273 ----
                  if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
                          EL(ha, "Unknown IP device=%xh\n", s_id.b24);
                          break;
                  }
  
!                 cnt = (uint16_t)(CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
                      CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0],
                      ha->ip_init_ctrl_blk.cb24.buf_size[1]) :
                      CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0],
                      ha->ip_init_ctrl_blk.cb.buf_size[1]));
  
*** 1243,1253 ****
  
                  tq->ub_seq_id = ++ha->ub_seq_id;
                  tq->ub_seq_cnt = 0;
                  tq->ub_frame_ro = 0;
                  tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ?
!                     (CFG_IST(ha, CFG_CTRL_24258081) ? BROADCAST_24XX_HDL :
                      IP_BROADCAST_LOOP_ID) : tq->loop_id);
                  ha->rcv_dev_q = tq;
  
                  for (cnt = 10; cnt < ha->reg_off->mbox_cnt &&
                      tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
--- 1285,1295 ----
  
                  tq->ub_seq_id = ++ha->ub_seq_id;
                  tq->ub_seq_cnt = 0;
                  tq->ub_frame_ro = 0;
                  tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ?
!                     (CFG_IST(ha, CFG_CTRL_24XX) ? BROADCAST_24XX_HDL :
                      IP_BROADCAST_LOOP_ID) : tq->loop_id);
                  ha->rcv_dev_q = tq;
  
                  for (cnt = 10; cnt < ha->reg_off->mbox_cnt &&
                      tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
*** 1277,1294 ****
                      "mbx1=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]));
                  break;
  
          case MBA_POINT_TO_POINT:
          /* case MBA_DCBX_COMPLETED: */
!                 if (CFG_IST(ha, CFG_CTRL_8081)) {
                          EL(ha, "%xh DCBX completed received\n", mb[0]);
                  } else {
                          EL(ha, "%xh Point to Point Mode received\n", mb[0]);
                  }
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags |= POINT_TO_POINT;
                  ADAPTER_STATE_UNLOCK(ha);
                  break;
  
          case MBA_FCF_CONFIG_ERROR:
                  EL(ha, "%xh FCF configuration Error received, mbx1=%xh\n",
                      mb[0], RD16_IO_REG(ha, mailbox_out[1]));
--- 1319,1344 ----
                      "mbx1=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]));
                  break;
  
          case MBA_POINT_TO_POINT:
          /* case MBA_DCBX_COMPLETED: */
!                 if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
                          EL(ha, "%xh DCBX completed received\n", mb[0]);
                  } else {
                          EL(ha, "%xh Point to Point Mode received\n", mb[0]);
                  }
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags |= POINT_TO_POINT;
                  ADAPTER_STATE_UNLOCK(ha);
+                 if (!(ha->task_daemon_flags & LOOP_DOWN)) {
+                         *set_flags |= LOOP_DOWN;
+                 }
+                 if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
+                         ha->loop_down_timer = LOOP_DOWN_TIMER_START;
+                 }
+                 ql_port_state(ha, FC_STATE_OFFLINE,
+                     FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
                  break;
  
          case MBA_FCF_CONFIG_ERROR:
                  EL(ha, "%xh FCF configuration Error received, mbx1=%xh\n",
                      mb[0], RD16_IO_REG(ha, mailbox_out[1]));
*** 1321,1333 ****
                  break;
  
          case MBA_ZIO_UPDATE:
                  EL(ha, "%xh ZIO response received\n", mb[0]);
  
!                 ha->isp_rsp_index = RD16_IO_REG(ha, resp_in);
!                 ql_response_pkt(ha, done_q, set_flags, reset_flags, intr_clr);
!                 intr = B_FALSE;
                  break;
  
          case MBA_PORT_BYPASS_CHANGED:
                  EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n",
                      mb[0], RD16_IO_REG(ha, mailbox_out[1]));
--- 1371,1382 ----
                  break;
  
          case MBA_ZIO_UPDATE:
                  EL(ha, "%xh ZIO response received\n", mb[0]);
  
!                 rsp_q->isp_rsp_index = RD16_IO_REG(ha, resp_in);
!                 ql_response_pkt(ha, rsp_q, done_q, set_flags, reset_flags);
                  break;
  
          case MBA_PORT_BYPASS_CHANGED:
                  EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n",
                      mb[0], RD16_IO_REG(ha, mailbox_out[1]));
*** 1362,1409 ****
          /*
           * MBA_IDC_COMPLETE &  MBA_IDC_NOTIFICATION: We won't get another
           * IDC async event until we ACK the current one.
           */
          case MBA_IDC_COMPLETE:
!                 ha->idc_mb[0] = mb[0];
!                 ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
!                 ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
!                 ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
!                 ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]);
!                 ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]);
!                 ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]);
!                 ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]);
!                 EL(ha, "%xh Inter-driver communication complete received, "
!                     " mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh,"
!                     " mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1],
!                     ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5],
!                     ha->idc_mb[6], ha->idc_mb[7]);
!                 *set_flags |= IDC_EVENT;
                  break;
  
          case MBA_IDC_NOTIFICATION:
!                 ha->idc_mb[0] = mb[0];
!                 ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
!                 ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
!                 ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
!                 ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]);
!                 ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]);
!                 ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]);
!                 ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]);
!                 EL(ha, "%xh Inter-driver communication request notification "
!                     "received, mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, "
!                     "mbx5=%xh, mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1],
!                     ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5],
!                     ha->idc_mb[6], ha->idc_mb[7]);
!                 *set_flags |= IDC_EVENT;
                  break;
  
          case MBA_IDC_TIME_EXTENDED:
!                 EL(ha, "%xh Inter-driver communication time extended received,"
!                     " mbx1=%xh, mbx2=%xh\n", mb[0],
!                     RD16_IO_REG(ha, mailbox_out[1]),
!                     RD16_IO_REG(ha, mailbox_out[2]));
                  break;
  
          default:
                  EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, "
                      "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
--- 1411,1480 ----
          /*
           * MBA_IDC_COMPLETE &  MBA_IDC_NOTIFICATION: We won't get another
           * IDC async event until we ACK the current one.
           */
          case MBA_IDC_COMPLETE:
!                 mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
!                 EL(ha, "%xh MBA_IDC_COMPLETE received, mbx2=%xh\n", mb[0],
!                     mb[2]);
!                 switch (mb[2]) {
!                 case IDC_OPC_FLASH_ACC:
!                 case IDC_OPC_RESTART_MPI:
!                 case IDC_OPC_PORT_RESET_MBC:
!                 case IDC_OPC_SET_PORT_CONFIG_MBC:
!                         ADAPTER_STATE_LOCK(ha);
!                         ha->flags |= IDC_RESTART_NEEDED;
!                         ADAPTER_STATE_UNLOCK(ha);
                          break;
+                 default:
+                         EL(ha, "unknown IDC completion opcode=%xh\n", mb[2]);
+                         break;
+                 }
+                 break;
  
          case MBA_IDC_NOTIFICATION:
!                 for (cnt = 1; cnt < 8; cnt++) {
!                         ha->idc_mb[cnt] = RD16_IO_REG(ha, mailbox_out[cnt]);
!                 }
!                 EL(ha, "%xh MBA_IDC_REQ_NOTIFICATION received, mbx1=%xh, "
!                     "mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh, mbx6=%xh, "
!                     "mbx7=%xh\n", mb[0], ha->idc_mb[1], ha->idc_mb[2],
!                     ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5], ha->idc_mb[6],
!                     ha->idc_mb[7]);
! 
!                 ADAPTER_STATE_LOCK(ha);
!                 switch (ha->idc_mb[2]) {
!                 case IDC_OPC_DRV_START:
!                         ha->flags |= IDC_RESTART_NEEDED;
                          break;
+                 case IDC_OPC_FLASH_ACC:
+                 case IDC_OPC_RESTART_MPI:
+                 case IDC_OPC_PORT_RESET_MBC:
+                 case IDC_OPC_SET_PORT_CONFIG_MBC:
+                         ha->flags |= IDC_STALL_NEEDED;
+                         break;
+                 default:
+                         EL(ha, "unknown IDC request opcode=%xh\n",
+                             ha->idc_mb[2]);
+                         break;
+                 }
+                 /*
+                  * If there is a timeout value associated with this IDC
+                  * notification then there is an implied requirement
+                  * that we return an ACK.
+                  */
+                 if (ha->idc_mb[1] & IDC_TIMEOUT_MASK) {
+                         ha->flags |= IDC_ACK_NEEDED;
+                 }
+                 ADAPTER_STATE_UNLOCK(ha);
  
+                 ql_awaken_task_daemon(ha, NULL, 0, 0);
+                 break;
+ 
          case MBA_IDC_TIME_EXTENDED:
!                 EL(ha, "%xh MBA_IDC_TIME_EXTENDED received, mbx2=%xh\n",
!                     mb[0], RD16_IO_REG(ha, mailbox_out[2]));
                  break;
  
          default:
                  EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, "
                      "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
*** 1410,1451 ****
                      RD16_IO_REG(ha, mailbox_out[2]),
                      RD16_IO_REG(ha, mailbox_out[3]));
                  break;
          }
  
!         /* Clear RISC interrupt */
!         if (intr && intr_clr) {
!                 if (CFG_IST(ha, CFG_CTRL_8021)) {
!                         ql_8021_clr_fw_intr(ha);
!                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
!                         WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
!                 } else {
!                         WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
!                 }
!         }
! 
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_fast_fcp_post
   *      Fast path for good SCSI I/O completion.
   *
   * Input:
   *      sp:     SRB pointer.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_fast_fcp_post(ql_srb_t *sp)
  {
          ql_adapter_state_t      *ha = sp->ha;
          ql_lun_t                *lq = sp->lun_queue;
          ql_tgt_t                *tq = lq->target_queue;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Acquire device queue lock. */
          DEVICE_QUEUE_LOCK(tq);
  
          /* Decrement outstanding commands on device. */
--- 1481,1512 ----
                      RD16_IO_REG(ha, mailbox_out[2]),
                      RD16_IO_REG(ha, mailbox_out[3]));
                  break;
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_fast_fcp_post
   *      Fast path for good SCSI I/O completion.
   *
   * Input:
   *      sp:     SRB pointer.
+  *      rsp_q:  response queue structure pointer.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_fast_fcp_post(ql_srb_t *sp, ql_response_q_t *rsp_q)
  {
          ql_adapter_state_t      *ha = sp->ha;
          ql_lun_t                *lq = sp->lun_queue;
          ql_tgt_t                *tq = lq->target_queue;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Acquire device queue lock. */
          DEVICE_QUEUE_LOCK(tq);
  
          /* Decrement outstanding commands on device. */
*** 1498,1674 ****
          /* Map ISP completion codes. */
          sp->pkt->pkt_expln = FC_EXPLN_NONE;
          sp->pkt->pkt_action = FC_ACTION_RETRYABLE;
          sp->pkt->pkt_state = FC_PKT_SUCCESS;
  
          /* Now call the pkt completion callback */
          if (sp->flags & SRB_POLL) {
                  sp->flags &= ~SRB_POLL;
!         } else if (sp->pkt->pkt_comp) {
!                 INTR_UNLOCK(ha);
                  (*sp->pkt->pkt_comp)(sp->pkt);
!                 INTR_LOCK(ha);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_response_pkt
   *      Processes response entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      done_q:         head pointer to done queue.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
-  *      intr_clr:       early interrupt clear
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_response_pkt(ql_adapter_state_t *ha, ql_head_t *done_q, uint32_t *set_flags,
!     uint32_t *reset_flags, int intr_clr)
  {
          response_t      *pkt;
          uint32_t        dma_sync_size_1 = 0;
          uint32_t        dma_sync_size_2 = 0;
          int             status = 0;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         /* Clear RISC interrupt */
!         if (intr_clr) {
!                 if (CFG_IST(ha, CFG_CTRL_8021)) {
!                         ql_8021_clr_fw_intr(ha);
!                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
!                         WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
!                 } else {
!                         WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
!                 }
!         }
! 
!         if (ha->isp_rsp_index >= RESPONSE_ENTRY_CNT) {
                  EL(ha, "index error = %xh, isp_abort_needed",
!                     ha->isp_rsp_index);
                  *set_flags |= ISP_ABORT_NEEDED;
                  return;
          }
  
          if ((ha->flags & ONLINE) == 0) {
!                 QL_PRINT_3(CE_CONT, "(%d): not onlne, done\n", ha->instance);
                  return;
          }
  
          /* Calculate size of response queue entries to sync. */
!         if (ha->isp_rsp_index > ha->rsp_ring_index) {
                  dma_sync_size_1 = (uint32_t)
!                     ((uint32_t)(ha->isp_rsp_index - ha->rsp_ring_index) *
                      RESPONSE_ENTRY_SIZE);
!         } else if (ha->isp_rsp_index == 0) {
                  dma_sync_size_1 = (uint32_t)
!                     ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
                      RESPONSE_ENTRY_SIZE);
          } else {
                  /* Responses wrap around the Q */
                  dma_sync_size_1 = (uint32_t)
!                     ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
                      RESPONSE_ENTRY_SIZE);
                  dma_sync_size_2 = (uint32_t)
!                     (ha->isp_rsp_index * RESPONSE_ENTRY_SIZE);
          }
  
          /* Sync DMA buffer. */
!         (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!             (off_t)(ha->rsp_ring_index * RESPONSE_ENTRY_SIZE +
!             RESPONSE_Q_BUFFER_OFFSET), dma_sync_size_1,
!             DDI_DMA_SYNC_FORKERNEL);
          if (dma_sync_size_2) {
!                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                     RESPONSE_Q_BUFFER_OFFSET, dma_sync_size_2,
!                     DDI_DMA_SYNC_FORKERNEL);
          }
  
!         while (ha->rsp_ring_index != ha->isp_rsp_index) {
!                 pkt = ha->response_ring_ptr;
  
!                 QL_PRINT_5(CE_CONT, "(%d): ha->rsp_rg_idx=%xh, mbx[5]=%xh\n",
!                     ha->instance, ha->rsp_ring_index, ha->isp_rsp_index);
!                 QL_DUMP_5((uint8_t *)ha->response_ring_ptr, 8,
                      RESPONSE_ENTRY_SIZE);
  
                  /* Adjust ring index. */
!                 ha->rsp_ring_index++;
!                 if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) {
!                         ha->rsp_ring_index = 0;
!                         ha->response_ring_ptr = ha->response_ring_bp;
                  } else {
!                         ha->response_ring_ptr++;
                  }
  
                  /* Process packet. */
!                 if (ha->status_srb != NULL && pkt->entry_type !=
!                     STATUS_CONT_TYPE) {
!                         ql_add_link_b(done_q, &ha->status_srb->cmd);
!                         ha->status_srb = NULL;
                  }
  
!                 pkt->entry_status = (uint8_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
                      pkt->entry_status & 0x3c : pkt->entry_status & 0x7e);
  
!                 if (pkt->entry_status != 0) {
!                         ql_error_entry(ha, pkt, done_q, set_flags,
!                             reset_flags);
                  } else {
                          switch (pkt->entry_type) {
                          case STATUS_TYPE:
!                                 status |= CFG_IST(ha, CFG_CTRL_24258081) ?
!                                     ql_24xx_status_entry(ha,
!                                     (sts_24xx_entry_t *)pkt, done_q, set_flags,
!                                     reset_flags) :
!                                     ql_status_entry(ha, (sts_entry_t *)pkt,
                                      done_q, set_flags, reset_flags);
                                  break;
                          case STATUS_CONT_TYPE:
!                                 ql_status_cont_entry(ha,
!                                     (sts_cont_entry_t *)pkt, done_q, set_flags,
!                                     reset_flags);
                                  break;
                          case IP_TYPE:
                          case IP_A64_TYPE:
                          case IP_CMD_TYPE:
!                                 ql_ip_entry(ha, (ip_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case IP_RECEIVE_TYPE:
!                                 ql_ip_rcv_entry(ha,
!                                     (ip_rcv_entry_t *)pkt, done_q, set_flags,
!                                     reset_flags);
                                  break;
                          case IP_RECEIVE_CONT_TYPE:
!                                 ql_ip_rcv_cont_entry(ha,
                                      (ip_rcv_cont_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case IP_24XX_RECEIVE_TYPE:
!                                 ql_ip_24xx_rcv_entry(ha,
                                      (ip_rcv_24xx_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case MS_TYPE:
!                                 ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case REPORT_ID_TYPE:
!                                 ql_report_id_entry(ha, (report_id_1_t *)pkt,
!                                     done_q, set_flags, reset_flags);
                                  break;
                          case ELS_PASSTHRU_TYPE:
!                                 ql_els_passthru_entry(ha,
!                                     (els_passthru_entry_rsp_t *)pkt,
!                                     done_q, set_flags, reset_flags);
                                  break;
                          case IP_BUF_POOL_TYPE:
                          case MARKER_TYPE:
                          case VP_MODIFY_TYPE:
                          case VP_CONTROL_TYPE:
--- 1559,1746 ----
          /* Map ISP completion codes. */
          sp->pkt->pkt_expln = FC_EXPLN_NONE;
          sp->pkt->pkt_action = FC_ACTION_RETRYABLE;
          sp->pkt->pkt_state = FC_PKT_SUCCESS;
  
+         (void) qlc_fm_check_pkt_dma_handle(ha, sp);
+ 
          /* Now call the pkt completion callback */
          if (sp->flags & SRB_POLL) {
                  sp->flags &= ~SRB_POLL;
!         } else if (ha->completion_thds == 1 && sp->pkt->pkt_comp &&
!             !(ha->flags & POLL_INTR)) {
!                 INDX_INTR_UNLOCK(ha, rsp_q->rsp_q_number);
                  (*sp->pkt->pkt_comp)(sp->pkt);
!                 INDX_INTR_LOCK(ha, rsp_q->rsp_q_number);
!         } else {
!                 ql_io_comp(sp);
          }
  
!         if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
!             != DDI_FM_OK) {
!                 qlc_fm_report_err_impact(ha,
!                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
!         }
! 
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_response_pkt
   *      Processes response entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      done_q:         head pointer to done queue.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_response_pkt(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
  {
          response_t      *pkt;
          uint32_t        dma_sync_size_1 = 0;
          uint32_t        dma_sync_size_2 = 0;
          int             status = 0;
  
!         QL_PRINT_3(ha, "started\n");
  
!         if (rsp_q->isp_rsp_index >= rsp_q->rsp_entry_cnt) {
                  EL(ha, "index error = %xh, isp_abort_needed",
!                     rsp_q->isp_rsp_index);
                  *set_flags |= ISP_ABORT_NEEDED;
                  return;
          }
  
          if ((ha->flags & ONLINE) == 0) {
!                 QL_PRINT_10(ha, "not onlne, done\n");
                  return;
          }
  
          /* Calculate size of response queue entries to sync. */
!         if (rsp_q->isp_rsp_index > rsp_q->rsp_ring_index) {
                  dma_sync_size_1 = (uint32_t)
!                     ((uint32_t)(rsp_q->isp_rsp_index - rsp_q->rsp_ring_index) *
                      RESPONSE_ENTRY_SIZE);
!         } else if (rsp_q->isp_rsp_index == 0) {
                  dma_sync_size_1 = (uint32_t)
!                     ((uint32_t)(rsp_q->rsp_entry_cnt - rsp_q->rsp_ring_index) *
                      RESPONSE_ENTRY_SIZE);
          } else {
                  /* Responses wrap around the Q */
                  dma_sync_size_1 = (uint32_t)
!                     ((uint32_t)(rsp_q->rsp_entry_cnt - rsp_q->rsp_ring_index) *
                      RESPONSE_ENTRY_SIZE);
                  dma_sync_size_2 = (uint32_t)
!                     (rsp_q->isp_rsp_index * RESPONSE_ENTRY_SIZE);
          }
  
          /* Sync DMA buffer. */
!         (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle,
!             (off_t)(rsp_q->rsp_ring_index * RESPONSE_ENTRY_SIZE),
!             dma_sync_size_1, DDI_DMA_SYNC_FORCPU);
          if (dma_sync_size_2) {
!                 (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle, 0,
!                     dma_sync_size_2, DDI_DMA_SYNC_FORCPU);
          }
  
!         if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
!             != DDI_FM_OK) {
!                 qlc_fm_report_err_impact(ha,
!                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
!         }
  
!         while (rsp_q->rsp_ring_index != rsp_q->isp_rsp_index) {
!                 pkt = rsp_q->rsp_ring_ptr;
! 
!                 QL_PRINT_5(ha, "ha->rsp_rg_idx=%xh, mbx[5]=%xh\n",
!                     rsp_q->rsp_ring_index, rsp_q->isp_rsp_index);
!                 QL_DUMP_5((uint8_t *)rsp_q->rsp_ring_ptr, 8,
                      RESPONSE_ENTRY_SIZE);
  
                  /* Adjust ring index. */
!                 rsp_q->rsp_ring_index++;
!                 if (rsp_q->rsp_ring_index == rsp_q->rsp_entry_cnt) {
!                         rsp_q->rsp_ring_index = 0;
!                         rsp_q->rsp_ring_ptr = rsp_q->rsp_ring.bp;
                  } else {
!                         rsp_q->rsp_ring_ptr++;
                  }
  
                  /* Process packet. */
!                 if (rsp_q->status_srb != NULL &&
!                     pkt->entry_type != STATUS_CONT_TYPE) {
!                         ql_add_link_b(done_q, &rsp_q->status_srb->cmd);
!                         rsp_q->status_srb = NULL;
                  }
  
!                 pkt->entry_status = (uint8_t)
!                     (CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
                      pkt->entry_status & 0x3c : pkt->entry_status & 0x7e);
  
!                 if (pkt->entry_status != 0 ||
!                     pkt->entry_type == ABORTED_ENTRY_TYPE) {
!                         ql_error_entry(ha, rsp_q,
!                             pkt, done_q,
!                             set_flags, reset_flags);
                  } else {
                          switch (pkt->entry_type) {
                          case STATUS_TYPE:
!                                 status |= CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
!                                     ql_24xx_status_entry(ha, rsp_q,
!                                     (sts_24xx_entry_t *)pkt, done_q,
!                                     set_flags, reset_flags) :
!                                     ql_status_entry(ha, rsp_q,
!                                     (sts_entry_t *)pkt,
                                      done_q, set_flags, reset_flags);
                                  break;
                          case STATUS_CONT_TYPE:
!                                 ql_status_cont_entry(ha, rsp_q,
!                                     (sts_cont_entry_t *)pkt, done_q,
!                                     set_flags, reset_flags);
                                  break;
                          case IP_TYPE:
                          case IP_A64_TYPE:
                          case IP_CMD_TYPE:
!                                 ql_ip_entry(ha, rsp_q,
!                                     (ip_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case IP_RECEIVE_TYPE:
!                                 ql_ip_rcv_entry(ha, rsp_q,
!                                     (ip_rcv_entry_t *)pkt, done_q,
!                                     set_flags, reset_flags);
                                  break;
                          case IP_RECEIVE_CONT_TYPE:
!                                 ql_ip_rcv_cont_entry(ha, rsp_q,
                                      (ip_rcv_cont_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case IP_24XX_RECEIVE_TYPE:
!                                 ql_ip_24xx_rcv_entry(ha, rsp_q,
                                      (ip_rcv_24xx_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case MS_TYPE:
!                                 ql_ms_entry(ha, rsp_q,
!                                     (ms_entry_t *)pkt, done_q,
                                      set_flags, reset_flags);
                                  break;
                          case REPORT_ID_TYPE:
!                                 ql_report_id_entry(ha, rsp_q,
!                                     (report_id_acq_t *)pkt, done_q,
!                                     set_flags, reset_flags);
                                  break;
                          case ELS_PASSTHRU_TYPE:
!                                 ql_els_passthru_entry(ha, rsp_q,
!                                     (els_passthru_entry_rsp_t *)pkt, done_q,
!                                     set_flags, reset_flags);
                                  break;
                          case IP_BUF_POOL_TYPE:
                          case MARKER_TYPE:
                          case VP_MODIFY_TYPE:
                          case VP_CONTROL_TYPE:
*** 1680,1727 ****
                          }
                  }
          }
  
          /* Inform RISC of processed responses. */
-         WRT16_IO_REG(ha, resp_out, ha->rsp_ring_index);
  
          /* RESET packet received delay for possible async event. */
          if (status & BIT_0) {
                  drv_usecwait(500000);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_error_entry
   *      Processes error entry.
   *
   * Input:
!  *      ha = adapter state pointer.
!  *      pkt = entry pointer.
!  *      done_q = head pointer to done queue.
!  *      set_flags = task daemon flags to set.
!  *      reset_flags = task daemon flags to reset.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_error_entry(ql_adapter_state_t *ha, response_t *pkt, ql_head_t *done_q,
!     uint32_t *set_flags, uint32_t *reset_flags)
  {
!         ql_srb_t        *sp;
          uint32_t        index, resp_identifier;
  
!         if (pkt->entry_type == INVALID_ENTRY_TYPE) {
!                 EL(ha, "Aborted command\n");
                  return;
          }
  
!         QL_PRINT_2(CE_CONT, "(%d): started, packet:\n", ha->instance);
          QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE);
  
          if (pkt->entry_status & BIT_6) {
                  EL(ha, "Request Queue DMA error\n");
          } else if (pkt->entry_status & BIT_5) {
--- 1752,1828 ----
                          }
                  }
          }
  
          /* Inform RISC of processed responses. */
  
+         if (ha->flags & MULTI_QUEUE) {
+                 WR32_MBAR_REG(ha, rsp_q->mbar_rsp_out, rsp_q->rsp_ring_index);
+         } else {
+                 WRT16_IO_REG(ha, resp_out, rsp_q->rsp_ring_index);
+         }
+ 
+         if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
+             != DDI_FM_OK) {
+                 qlc_fm_report_err_impact(ha,
+                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
+         }
+ 
          /* RESET packet received delay for possible async event. */
          if (status & BIT_0) {
                  drv_usecwait(500000);
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_error_entry
   *      Processes error entry.
   *
   * Input:
!  *      ha:             adapter state pointer.
!  *      rsp_q:          response queue structure pointer.
!  *      pkt:            entry pointer.
!  *      done_q:         head pointer to done queue.
!  *      set_flags:      task daemon flags to set.
!  *      reset_flags:    task daemon flags to reset.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_error_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, response_t *pkt,
!     ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
  {
!         ql_srb_t        *sp = NULL;
          uint32_t        index, resp_identifier;
  
!         if (pkt->entry_type == ABORTED_ENTRY_TYPE) {
!                 resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
!                     &pkt->handle);
!                 index = resp_identifier & OSC_INDEX_MASK;
!                 if (index < ha->osc_max_cnt) {
!                         if (ha->outstanding_cmds[index] ==
!                             QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "Aborted command sp=QL_ABORTED_SRB, "
!                                     "handle=%xh\n", resp_identifier);
!                                 ha->outstanding_cmds[index] = NULL;
!                         } else {
!                                 EL(ha, "Aborted command sp=%ph, handle=%xh\n",
!                                     (void *) ha->outstanding_cmds[index],
!                                     resp_identifier);
!                         }
!                 } else {
!                         EL(ha, "Aborted command handle=%xh, out of range "
!                             "index=%xh\n", resp_identifier, index);
!                 }
                  return;
          }
  
!         QL_PRINT_2(ha, "started, packet:\n");
          QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE);
  
          if (pkt->entry_status & BIT_6) {
                  EL(ha, "Request Queue DMA error\n");
          } else if (pkt->entry_status & BIT_5) {
*** 1737,1753 ****
          } else {
                  EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status);
          }
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < MAX_OUTSTANDING_COMMANDS) {
                  /* the index seems reasonable */
!                 sp = ha->outstanding_cmds[index];
                  if (sp != NULL) {
!                         if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
--- 1838,1864 ----
          } else {
                  EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status);
          }
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &pkt->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < ha->osc_max_cnt) {
                  /* the index seems reasonable */
!                 if ((sp = ha->outstanding_cmds[index]) == NULL) {
!                         sp = ql_verify_preprocessed_cmd(ha, rsp_q,
!                             (uint32_t *)&pkt->handle,
!                             (uint32_t *)&resp_identifier, set_flags,
!                             reset_flags);
!                 }
                  if (sp != NULL) {
!                         if (sp == QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "QL_ABORTED_SRB handle=%xh\n",
!                                     resp_identifier);
!                                 sp = NULL;
!                                 ha->outstanding_cmds[index] = NULL;
!                         } else if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
*** 1754,1766 ****
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, sp->handle);
                                  sp = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
-                 } else {
-                         sp = ql_verify_preprocessed_cmd(ha,
-                             (uint32_t *)&pkt->handle, set_flags, reset_flags);
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
--- 1865,1874 ----
*** 1783,1801 ****
  
                  /* Place command on done queue. */
                  ql_add_link_b(done_q, &sp->cmd);
  
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_status_entry
   *      Processes received ISP2200-2300 status entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 1891,1910 ----
  
                  /* Place command on done queue. */
                  ql_add_link_b(done_q, &sp->cmd);
  
          }
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_status_entry
   *      Processes received ISP2200-2300 status entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 1805,1832 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static int
! ql_status_entry(ql_adapter_state_t *ha, sts_entry_t *pkt,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
!         ql_srb_t                *sp;
          uint32_t                index, resp_identifier;
          uint16_t                comp_status;
          int                     rval = 0;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < MAX_OUTSTANDING_COMMANDS) {
                  /* the index seems reasonable */
!                 sp = ha->outstanding_cmds[index];
                  if (sp != NULL) {
!                         if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
--- 1914,1952 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static int
! ql_status_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     sts_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
!         ql_srb_t                *sp = NULL;
          uint32_t                index, resp_identifier;
          uint16_t                comp_status;
          int                     rval = 0;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &pkt->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < ha->osc_max_cnt) {
                  /* the index seems reasonable */
!                 if ((sp = ha->outstanding_cmds[index]) == NULL) {
!                         sp = ql_verify_preprocessed_cmd(ha, rsp_q,
!                             (uint32_t *)&pkt->handle,
!                             (uint32_t *)&resp_identifier, set_flags,
!                             reset_flags);
!                 }
                  if (sp != NULL) {
!                         if (sp == QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "QL_ABORTED_SRB handle=%xh\n",
!                                     resp_identifier);
!                                 sp = NULL;
!                                 ha->outstanding_cmds[index] = NULL;
!                         } else if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
*** 1833,1854 ****
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, sp->handle);
                                  sp = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
-                 } else {
-                         sp = ql_verify_preprocessed_cmd(ha,
-                             (uint32_t *)&pkt->handle, set_flags, reset_flags);
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
          }
  
          if (sp != NULL) {
!                 comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
                      &pkt->comp_status);
  
                  /*
                   * We dont care about SCSI QFULLs.
                   */
--- 1953,1971 ----
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, sp->handle);
                                  sp = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
          }
  
          if (sp != NULL) {
!                 comp_status = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
                      &pkt->comp_status);
  
                  /*
                   * We dont care about SCSI QFULLs.
                   */
*** 1861,1883 ****
  
                  /*
                   * 2300 firmware marks completion status as data underrun
                   * for scsi qfulls. Make it transport complete.
                   */
!                 if ((CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) &&
!                     (comp_status == CS_DATA_UNDERRUN) &&
!                     (pkt->scsi_status_l != 0)) {
                          comp_status = CS_COMPLETE;
                  }
  
                  /*
                   * Workaround T3 issue where we do not get any data xferred
                   * but get back a good status.
                   */
                  if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 &&
                      comp_status == CS_COMPLETE &&
!                     pkt->scsi_status_l == 0 &&
                      (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
                      pkt->residual_length == 0 &&
                      sp->fcp &&
                      sp->fcp->fcp_data_len != 0 &&
                      (pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) ==
--- 1978,2000 ----
  
                  /*
                   * 2300 firmware marks completion status as data underrun
                   * for scsi qfulls. Make it transport complete.
                   */
!                 if (CFG_IST(ha, CFG_CTRL_2363) &&
!                     comp_status == CS_DATA_UNDERRUN &&
!                     pkt->scsi_status_l != STATUS_GOOD) {
                          comp_status = CS_COMPLETE;
                  }
  
                  /*
                   * Workaround T3 issue where we do not get any data xferred
                   * but get back a good status.
                   */
                  if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 &&
                      comp_status == CS_COMPLETE &&
!                     pkt->scsi_status_l == STATUS_GOOD &&
                      (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
                      pkt->residual_length == 0 &&
                      sp->fcp &&
                      sp->fcp->fcp_data_len != 0 &&
                      (pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) ==
*** 1890,1924 ****
                           * Ideally it should never be true. But there
                           * is a bug in FW which upon receiving invalid
                           * parameters in MS IOCB returns it as
                           * status entry and not as ms entry type.
                           */
!                         ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
                              set_flags, reset_flags);
!                         QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n",
!                             ha->instance);
                          return (0);
                  }
  
                  /*
                   * Fast path to good SCSI I/O completion
                   */
!                 if ((comp_status == CS_COMPLETE) &
!                     (!pkt->scsi_status_l) &
!                     (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
                          /* Set completed status. */
                          sp->flags |= SRB_ISP_COMPLETED;
                          sp->pkt->pkt_reason = comp_status;
!                         ql_fast_fcp_post(sp);
!                         QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
!                             ha->instance);
                          return (0);
                  }
!                 rval = ql_status_error(ha, sp, pkt, done_q, set_flags,
                      reset_flags);
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 2007,2039 ----
                           * Ideally it should never be true. But there
                           * is a bug in FW which upon receiving invalid
                           * parameters in MS IOCB returns it as
                           * status entry and not as ms entry type.
                           */
!                         ql_ms_entry(ha, rsp_q, (ms_entry_t *)pkt, done_q,
                              set_flags, reset_flags);
!                         QL_PRINT_3(ha, "ql_ms_entry done\n");
                          return (0);
                  }
  
                  /*
                   * Fast path to good SCSI I/O completion
                   */
!                 if (comp_status == CS_COMPLETE &&
!                     pkt->scsi_status_l == STATUS_GOOD &&
!                     (pkt->scsi_status_h & FCP_RSP_MASK) == 0) {
                          /* Set completed status. */
                          sp->flags |= SRB_ISP_COMPLETED;
                          sp->pkt->pkt_reason = comp_status;
!                         ql_fast_fcp_post(sp, rsp_q);
!                         QL_PRINT_3(ha, "ql_fast_fcp_post done\n");
                          return (0);
                  }
!                 rval = ql_status_error(ha, rsp_q, sp, pkt, done_q, set_flags,
                      reset_flags);
          }
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 1925,1934 ****
--- 2040,2050 ----
   * ql_24xx_status_entry
   *      Processes received ISP24xx status entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 1938,1965 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static int
! ql_24xx_status_entry(ql_adapter_state_t *ha, sts_24xx_entry_t *pkt,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          ql_srb_t                *sp = NULL;
          uint16_t                comp_status;
          uint32_t                index, resp_identifier;
          int                     rval = 0;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < MAX_OUTSTANDING_COMMANDS) {
                  /* the index seems reasonable */
!                 sp = ha->outstanding_cmds[index];
                  if (sp != NULL) {
!                         if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
--- 2054,2092 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static int
! ql_24xx_status_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     sts_24xx_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          ql_srb_t                *sp = NULL;
          uint16_t                comp_status;
          uint32_t                index, resp_identifier;
          int                     rval = 0;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &pkt->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < ha->osc_max_cnt) {
                  /* the index seems reasonable */
!                 if ((sp = ha->outstanding_cmds[index]) == NULL) {
!                         sp = ql_verify_preprocessed_cmd(ha, rsp_q,
!                             (uint32_t *)&pkt->handle,
!                             (uint32_t *)&resp_identifier, set_flags,
!                             reset_flags);
!                 }
                  if (sp != NULL) {
!                         if (sp == QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "QL_ABORTED_SRB handle=%xh\n",
!                                     resp_identifier);
!                                 sp = NULL;
!                                 ha->outstanding_cmds[index] = NULL;
!                         } else if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
*** 1966,1987 ****
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, sp->handle);
                                  sp = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
-                 } else {
-                         sp = ql_verify_preprocessed_cmd(ha,
-                             (uint32_t *)&pkt->handle, set_flags, reset_flags);
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
          }
  
          if (sp != NULL) {
!                 comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
                      &pkt->comp_status);
  
                  /* We dont care about SCSI QFULLs. */
                  if (comp_status == CS_QUEUE_FULL) {
                          EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
--- 2093,2111 ----
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, sp->handle);
                                  sp = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
          }
  
          if (sp != NULL) {
!                 comp_status = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
                      &pkt->comp_status);
  
                  /* We dont care about SCSI QFULLs. */
                  if (comp_status == CS_QUEUE_FULL) {
                          EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
*** 1992,2012 ****
  
                  /*
                   * 2300 firmware marks completion status as data underrun
                   * for scsi qfulls. Make it transport complete.
                   */
!                 if ((comp_status == CS_DATA_UNDERRUN) &&
!                     (pkt->scsi_status_l != 0)) {
                          comp_status = CS_COMPLETE;
                  }
  
                  /*
                   * Workaround T3 issue where we do not get any data xferred
                   * but get back a good status.
                   */
                  if (comp_status == CS_COMPLETE &&
!                     pkt->scsi_status_l == 0 &&
                      (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
                      pkt->residual_length != 0 &&
                      sp->fcp &&
                      sp->fcp->fcp_data_len != 0 &&
                      sp->fcp->fcp_cntl.cntl_write_data) {
--- 2116,2136 ----
  
                  /*
                   * 2300 firmware marks completion status as data underrun
                   * for scsi qfulls. Make it transport complete.
                   */
!                 if (comp_status == CS_DATA_UNDERRUN &&
!                     pkt->scsi_status_l != STATUS_GOOD) {
                          comp_status = CS_COMPLETE;
                  }
  
                  /*
                   * Workaround T3 issue where we do not get any data xferred
                   * but get back a good status.
                   */
                  if (comp_status == CS_COMPLETE &&
!                     pkt->scsi_status_l == STATUS_GOOD &&
                      (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
                      pkt->residual_length != 0 &&
                      sp->fcp &&
                      sp->fcp->fcp_data_len != 0 &&
                      sp->fcp->fcp_cntl.cntl_write_data) {
*** 2014,2038 ****
                  }
  
                  /*
                   * Fast path to good SCSI I/O completion
                   */
!                 if ((comp_status == CS_COMPLETE) &
!                     (!pkt->scsi_status_l) &
!                     (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
                          /* Set completed status. */
                          sp->flags |= SRB_ISP_COMPLETED;
                          sp->pkt->pkt_reason = comp_status;
!                         ql_fast_fcp_post(sp);
!                         QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
!                             ha->instance);
                          return (0);
                  }
!                 rval = ql_status_error(ha, sp, (sts_entry_t *)pkt, done_q,
!                     set_flags, reset_flags);
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 2138,2161 ----
                  }
  
                  /*
                   * Fast path to good SCSI I/O completion
                   */
!                 if (comp_status == CS_COMPLETE &&
!                     pkt->scsi_status_l == STATUS_GOOD &&
!                     (pkt->scsi_status_h & FCP_RSP_MASK) == 0) {
                          /* Set completed status. */
                          sp->flags |= SRB_ISP_COMPLETED;
                          sp->pkt->pkt_reason = comp_status;
!                         ql_fast_fcp_post(sp, rsp_q);
!                         QL_PRINT_3(ha, "ql_fast_fcp_post done\n");
                          return (0);
                  }
!                 rval = ql_status_error(ha, rsp_q, sp, (sts_entry_t *)pkt,
!                     done_q, set_flags, reset_flags);
          }
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 2039,2049 ****
--- 2162,2174 ----
   * ql_verify_preprocessed_cmd
   *      Handles preprocessed cmds..
   *
   * Input:
   *      ha:                     adapter state pointer.
+  *      rsp_q:                  response queue structure pointer.
   *      pkt_handle:             handle pointer.
+  *      resp_identifier:        resp_identifier pointer.
   *      set_flags:              task daemon flags to set.
   *      reset_flags:            task daemon flags to reset.
   *
   * Returns:
   *      srb pointer or NULL
*** 2051,2095 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  ql_srb_t *
! ql_verify_preprocessed_cmd(ql_adapter_state_t *ha, uint32_t *pkt_handle,
!     uint32_t *set_flags, uint32_t *reset_flags)
  {
          ql_srb_t                *sp = NULL;
!         uint32_t                index, resp_identifier;
          uint32_t                get_handle = 10;
  
          while (get_handle) {
                  /* Get handle. */
!                 resp_identifier = ddi_get32(ha->hba_buf.acc_handle, pkt_handle);
!                 index = resp_identifier & OSC_INDEX_MASK;
                  /* Validate handle. */
!                 if (index < MAX_OUTSTANDING_COMMANDS) {
                          sp = ha->outstanding_cmds[index];
                  }
  
                  if (sp != NULL) {
                          EL(ha, "sp=%xh, resp_id=%xh, get=%d, index=%xh\n", sp,
!                             resp_identifier, get_handle, index);
                          break;
                  } else {
                          get_handle -= 1;
                          drv_usecwait(10000);
!                         if (get_handle == 1) {
                                  /* Last chance, Sync whole DMA buffer. */
!                                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                                     RESPONSE_Q_BUFFER_OFFSET,
!                                     RESPONSE_QUEUE_SIZE,
!                                     DDI_DMA_SYNC_FORKERNEL);
                                  EL(ha, "last chance DMA sync, index=%xh\n",
                                      index);
                          }
                  }
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (sp);
  }
  
  
--- 2176,2220 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  ql_srb_t *
! ql_verify_preprocessed_cmd(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     uint32_t *pkt_handle, uint32_t *resp_identifier, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          ql_srb_t                *sp = NULL;
!         uint32_t                index;
          uint32_t                get_handle = 10;
  
          while (get_handle) {
                  /* Get handle. */
!                 *resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
!                     pkt_handle);
!                 index = *resp_identifier & OSC_INDEX_MASK;
                  /* Validate handle. */
!                 if (index < ha->osc_max_cnt) {
                          sp = ha->outstanding_cmds[index];
                  }
  
                  if (sp != NULL) {
                          EL(ha, "sp=%xh, resp_id=%xh, get=%d, index=%xh\n", sp,
!                             *resp_identifier, get_handle, index);
                          break;
                  } else {
                          get_handle -= 1;
                          drv_usecwait(10000);
!                         if (get_handle == 1 && rsp_q->rsp_ring.dma_handle) {
                                  /* Last chance, Sync whole DMA buffer. */
!                                 (void) ddi_dma_sync(rsp_q->rsp_ring.dma_handle,
!                                     0, 0, DDI_DMA_SYNC_FORCPU);
                                  EL(ha, "last chance DMA sync, index=%xh\n",
                                      index);
                          }
                  }
          }
!         QL_PRINT_3(ha, "done\n");
  
          return (sp);
  }
  
  
*** 2097,2106 ****
--- 2222,2232 ----
   * ql_status_error
   *      Processes received ISP status entry error.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      sp:             SRB pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
*** 2111,2122 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static int
! ql_status_error(ql_adapter_state_t *ha, ql_srb_t *sp, sts_entry_t *pkt23,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          uint32_t                sense_sz = 0;
          uint32_t                cnt;
          ql_tgt_t                *tq;
          fcp_rsp_t               *fcpr;
--- 2237,2249 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static int
! ql_status_error(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, ql_srb_t *sp,
!     sts_entry_t *pkt23, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          uint32_t                sense_sz = 0;
          uint32_t                cnt;
          ql_tgt_t                *tq;
          fcp_rsp_t               *fcpr;
*** 2135,2164 ****
                  uint8_t         state_flags_h;
                  uint8_t         scsi_status_l;
                  uint8_t         scsi_status_h;
          } sts;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (CFG_IST(ha, CFG_CTRL_24258081)) {
                  sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23;
  
                  /* Setup status. */
!                 sts.comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
!                     &pkt24->comp_status);
                  sts.scsi_status_l = pkt24->scsi_status_l;
                  sts.scsi_status_h = pkt24->scsi_status_h;
  
                  /* Setup firmware residuals. */
                  sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
!                     ddi_get32(ha->hba_buf.acc_handle,
                      (uint32_t *)&pkt24->residual_length) : 0;
  
                  /* Setup FCP residuals. */
                  sts.fcp_residual_length = sts.scsi_status_h &
                      (FCP_RESID_UNDER | FCP_RESID_OVER) ?
!                     ddi_get32(ha->hba_buf.acc_handle,
                      (uint32_t *)&pkt24->fcp_rsp_residual_count) : 0;
  
                  if ((sts.comp_status == CS_DATA_UNDERRUN) &&
                      (sts.scsi_status_h & FCP_RESID_UNDER) &&
                      (sts.residual_length != pkt24->fcp_rsp_residual_count)) {
--- 2262,2291 ----
                  uint8_t         state_flags_h;
                  uint8_t         scsi_status_l;
                  uint8_t         scsi_status_h;
          } sts;
  
!         QL_PRINT_3(ha, "started\n");
  
!         if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                  sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23;
  
                  /* Setup status. */
!                 sts.comp_status = (uint16_t)ddi_get16(
!                     rsp_q->rsp_ring.acc_handle, &pkt24->comp_status);
                  sts.scsi_status_l = pkt24->scsi_status_l;
                  sts.scsi_status_h = pkt24->scsi_status_h;
  
                  /* Setup firmware residuals. */
                  sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
!                     ddi_get32(rsp_q->rsp_ring.acc_handle,
                      (uint32_t *)&pkt24->residual_length) : 0;
  
                  /* Setup FCP residuals. */
                  sts.fcp_residual_length = sts.scsi_status_h &
                      (FCP_RESID_UNDER | FCP_RESID_OVER) ?
!                     ddi_get32(rsp_q->rsp_ring.acc_handle,
                      (uint32_t *)&pkt24->fcp_rsp_residual_count) : 0;
  
                  if ((sts.comp_status == CS_DATA_UNDERRUN) &&
                      (sts.scsi_status_h & FCP_RESID_UNDER) &&
                      (sts.residual_length != pkt24->fcp_rsp_residual_count)) {
*** 2206,2216 ****
                  }
  
                  /* Setup FCP response info. */
                  sts.rsp_info = &pkt24->rsp_sense_data[0];
                  if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
!                         sts.rsp_info_length = ddi_get32(ha->hba_buf.acc_handle,
                              (uint32_t *)&pkt24->fcp_rsp_data_length);
                          if (sts.rsp_info_length >
                              sizeof (struct fcp_rsp_info)) {
                                  sts.rsp_info_length =
                                      sizeof (struct fcp_rsp_info);
--- 2333,2344 ----
                  }
  
                  /* Setup FCP response info. */
                  sts.rsp_info = &pkt24->rsp_sense_data[0];
                  if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
!                         sts.rsp_info_length = ddi_get32(
!                             rsp_q->rsp_ring.acc_handle,
                              (uint32_t *)&pkt24->fcp_rsp_data_length);
                          if (sts.rsp_info_length >
                              sizeof (struct fcp_rsp_info)) {
                                  sts.rsp_info_length =
                                      sizeof (struct fcp_rsp_info);
*** 2225,2235 ****
                  /* Setup sense data. */
                  sts.req_sense_data =
                      &pkt24->rsp_sense_data[sts.rsp_info_length];
                  if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
                          sts.req_sense_length =
!                             ddi_get32(ha->hba_buf.acc_handle,
                              (uint32_t *)&pkt24->fcp_sense_length);
                          sts.state_flags_h = (uint8_t)
                              (sts.state_flags_h | SF_ARQ_DONE);
                          sense_sz = (uint32_t)
                              (((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) -
--- 2353,2363 ----
                  /* Setup sense data. */
                  sts.req_sense_data =
                      &pkt24->rsp_sense_data[sts.rsp_info_length];
                  if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
                          sts.req_sense_length =
!                             ddi_get32(rsp_q->rsp_ring.acc_handle,
                              (uint32_t *)&pkt24->fcp_sense_length);
                          sts.state_flags_h = (uint8_t)
                              (sts.state_flags_h | SF_ARQ_DONE);
                          sense_sz = (uint32_t)
                              (((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) -
*** 2241,2257 ****
                          sts.req_sense_length = 0;
                  }
          } else {
                  /* Setup status. */
                  sts.comp_status = (uint16_t)ddi_get16(
!                     ha->hba_buf.acc_handle, &pkt23->comp_status);
                  sts.scsi_status_l = pkt23->scsi_status_l;
                  sts.scsi_status_h = pkt23->scsi_status_h;
  
                  /* Setup firmware residuals. */
                  sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
!                     ddi_get32(ha->hba_buf.acc_handle,
                      (uint32_t *)&pkt23->residual_length) : 0;
  
                  /* Setup FCP residuals. */
                  sts.fcp_residual_length = sts.scsi_status_h &
                      (FCP_RESID_UNDER | FCP_RESID_OVER) ?
--- 2369,2385 ----
                          sts.req_sense_length = 0;
                  }
          } else {
                  /* Setup status. */
                  sts.comp_status = (uint16_t)ddi_get16(
!                     rsp_q->rsp_ring.acc_handle, &pkt23->comp_status);
                  sts.scsi_status_l = pkt23->scsi_status_l;
                  sts.scsi_status_h = pkt23->scsi_status_h;
  
                  /* Setup firmware residuals. */
                  sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
!                     ddi_get32(rsp_q->rsp_ring.acc_handle,
                      (uint32_t *)&pkt23->residual_length) : 0;
  
                  /* Setup FCP residuals. */
                  sts.fcp_residual_length = sts.scsi_status_h &
                      (FCP_RESID_UNDER | FCP_RESID_OVER) ?
*** 2263,2273 ****
  
                  /* Setup FCP response info. */
                  sts.rsp_info = &pkt23->rsp_info[0];
                  if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
                          sts.rsp_info_length = ddi_get16(
!                             ha->hba_buf.acc_handle,
                              (uint16_t *)&pkt23->rsp_info_length);
                          if (sts.rsp_info_length >
                              sizeof (struct fcp_rsp_info)) {
                                  sts.rsp_info_length =
                                      sizeof (struct fcp_rsp_info);
--- 2391,2401 ----
  
                  /* Setup FCP response info. */
                  sts.rsp_info = &pkt23->rsp_info[0];
                  if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
                          sts.rsp_info_length = ddi_get16(
!                             rsp_q->rsp_ring.acc_handle,
                              (uint16_t *)&pkt23->rsp_info_length);
                          if (sts.rsp_info_length >
                              sizeof (struct fcp_rsp_info)) {
                                  sts.rsp_info_length =
                                      sizeof (struct fcp_rsp_info);
*** 2277,2287 ****
                  }
  
                  /* Setup sense data. */
                  sts.req_sense_data = &pkt23->req_sense_data[0];
                  sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ?
!                     ddi_get16(ha->hba_buf.acc_handle,
                      (uint16_t *)&pkt23->req_sense_length) : 0;
          }
  
          bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen);
  
--- 2405,2415 ----
                  }
  
                  /* Setup sense data. */
                  sts.req_sense_data = &pkt23->req_sense_data[0];
                  sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ?
!                     ddi_get16(rsp_q->rsp_ring.acc_handle,
                      (uint16_t *)&pkt23->req_sense_length) : 0;
          }
  
          bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen);
  
*** 2318,2329 ****
                          sense_sz = sts.rsp_info_length;
                  }
  
                  /* copy response information data. */
                  if (sense_sz) {
!                         ddi_rep_get8(ha->hba_buf.acc_handle, (uint8_t *)rsp,
!                             sts.rsp_info, sense_sz, DDI_DEV_AUTOINCR);
                  }
                  fcpr->fcp_response_len = sense_sz;
  
                  rsp = (struct fcp_rsp_info *)((caddr_t)rsp +
                      fcpr->fcp_response_len);
--- 2446,2458 ----
                          sense_sz = sts.rsp_info_length;
                  }
  
                  /* copy response information data. */
                  if (sense_sz) {
!                         ddi_rep_get8(rsp_q->rsp_ring.acc_handle,
!                             (uint8_t *)rsp, sts.rsp_info, sense_sz,
!                             DDI_DEV_AUTOINCR);
                  }
                  fcpr->fcp_response_len = sense_sz;
  
                  rsp = (struct fcp_rsp_info *)((caddr_t)rsp +
                      fcpr->fcp_response_len);
*** 2358,2367 ****
--- 2487,2497 ----
                  fcpr->fcp_response_len = 0;
          }
  
          /* Set reset status received. */
          if (sts.comp_status == CS_RESET && LOOP_READY(ha)) {
+                 *set_flags |= MARKER_NEEDED;
                  rval |= BIT_0;
          }
  
          if (!(tq->flags & TQF_TAPE_DEVICE) &&
              (!(CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) ||
*** 2446,2456 ****
--- 2576,2591 ----
                                  ADAPTER_STATE_UNLOCK(ha);
                          }
                  } else {
                          EL(sp->ha, "Abort Retry, d_id=%xh, lun=%xh\n",
                              tq->d_id.b24, sp->lun_queue->lun_no);
+ 
+                         if (CFG_IST(ha, CFG_ISP_FW_TYPE_2) && LOOP_READY(ha)) {
+                                 *set_flags |= MARKER_NEEDED;
+                                 rval |= BIT_0;
                          }
+                 }
  
                  /* Set retry status. */
                  sp->flags |= SRB_RETRY;
          } else {
                  fcpr->fcp_resid =
*** 2479,2491 ****
                          sp->pkt->pkt_reason = CS_COMPLETE;
                  }
  
                  if (sp->pkt->pkt_reason != CS_COMPLETE) {
                          ha->xioctl->DeviceErrorCount++;
!                         EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh"
!                             "\n", sts.comp_status, tq->d_id.b24,
!                             sp->lun_queue->lun_no);
                  }
  
                  /* Set target request sense data. */
                  if (sts.scsi_status_l == STATUS_CHECK) {
                          if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
--- 2614,2628 ----
                          sp->pkt->pkt_reason = CS_COMPLETE;
                  }
  
                  if (sp->pkt->pkt_reason != CS_COMPLETE) {
                          ha->xioctl->DeviceErrorCount++;
!                         EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh,"
!                             " pkt_reason=%xh, spf=%xh, sp=%ph\n",
!                             sts.comp_status, tq->d_id.b24,
!                             sp->lun_queue->lun_no, sp->pkt->pkt_reason,
!                             sp->flags, sp);
                  }
  
                  /* Set target request sense data. */
                  if (sts.scsi_status_l == STATUS_CHECK) {
                          if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
*** 2530,2550 ****
                                  }
  
                                  fcpr->fcp_sense_len = sense_sz;
  
                                  /* Move sense data. */
!                                 ddi_rep_get8(ha->hba_buf.acc_handle,
                                      (uint8_t *)sp->request_sense_ptr,
                                      sts.req_sense_data,
                                      (size_t)sense_sz,
                                      DDI_DEV_AUTOINCR);
  
                                  sp->request_sense_ptr += sense_sz;
                                  sp->request_sense_length -= sense_sz;
                                  if (sp->request_sense_length != 0 &&
!                                     !(CFG_IST(ha, CFG_CTRL_8021))) {
!                                         ha->status_srb = sp;
                                  }
                          }
  
                          if (sense_sz != 0) {
                                  EL(sp->ha, "check condition sense data, "
--- 2667,2687 ----
                                  }
  
                                  fcpr->fcp_sense_len = sense_sz;
  
                                  /* Move sense data. */
!                                 ddi_rep_get8(rsp_q->rsp_ring.acc_handle,
                                      (uint8_t *)sp->request_sense_ptr,
                                      sts.req_sense_data,
                                      (size_t)sense_sz,
                                      DDI_DEV_AUTOINCR);
  
                                  sp->request_sense_ptr += sense_sz;
                                  sp->request_sense_length -= sense_sz;
                                  if (sp->request_sense_length != 0 &&
!                                     !(CFG_IST(ha, CFG_CTRL_82XX))) {
!                                         rsp_q->status_srb = sp;
                                  }
                          }
  
                          if (sense_sz != 0) {
                                  EL(sp->ha, "check condition sense data, "
*** 2579,2593 ****
  
          /* Set completed status. */
          sp->flags |= SRB_ISP_COMPLETED;
  
          /* Place command on done queue. */
!         if (ha->status_srb == NULL) {
                  ql_add_link_b(done_q, &sp->cmd);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 2716,2730 ----
  
          /* Set completed status. */
          sp->flags |= SRB_ISP_COMPLETED;
  
          /* Place command on done queue. */
!         if (rsp_q->status_srb == NULL) {
                  ql_add_link_b(done_q, &sp->cmd);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 2594,2603 ****
--- 2731,2741 ----
   * ql_status_cont_entry
   *      Processes status continuation entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 2604,2637 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_status_cont_entry(ql_adapter_state_t *ha, sts_cont_entry_t *pkt,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          uint32_t        sense_sz, index;
!         ql_srb_t        *sp = ha->status_srb;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (sp != NULL && sp->request_sense_length) {
                  if (sp->request_sense_length > sizeof (pkt->req_sense_data)) {
                          sense_sz = sizeof (pkt->req_sense_data);
                  } else {
                          sense_sz = sp->request_sense_length;
                  }
  
!                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
                          for (index = 0; index < sense_sz; index += 4) {
                                  ql_chg_endian((uint8_t *)
                                      &pkt->req_sense_data[0] + index, 4);
                          }
                  }
  
                  /* Move sense data. */
!                 ddi_rep_get8(ha->hba_buf.acc_handle,
                      (uint8_t *)sp->request_sense_ptr,
                      (uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz,
                      DDI_DEV_AUTOINCR);
  
                  sp->request_sense_ptr += sense_sz;
--- 2742,2776 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_status_cont_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     sts_cont_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          uint32_t        sense_sz, index;
!         ql_srb_t        *sp = rsp_q->status_srb;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (sp != NULL && sp->request_sense_length) {
                  if (sp->request_sense_length > sizeof (pkt->req_sense_data)) {
                          sense_sz = sizeof (pkt->req_sense_data);
                  } else {
                          sense_sz = sp->request_sense_length;
                  }
  
!                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                          for (index = 0; index < sense_sz; index += 4) {
                                  ql_chg_endian((uint8_t *)
                                      &pkt->req_sense_data[0] + index, 4);
                          }
                  }
  
                  /* Move sense data. */
!                 ddi_rep_get8(rsp_q->rsp_ring.acc_handle,
                      (uint8_t *)sp->request_sense_ptr,
                      (uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz,
                      DDI_DEV_AUTOINCR);
  
                  sp->request_sense_ptr += sense_sz;
*** 2638,2660 ****
                  sp->request_sense_length -= sense_sz;
  
                  /* Place command on done queue. */
                  if (sp->request_sense_length == 0) {
                          ql_add_link_b(done_q, &sp->cmd);
!                         ha->status_srb = NULL;
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_ip_entry
   *      Processes received ISP IP entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 2777,2800 ----
                  sp->request_sense_length -= sense_sz;
  
                  /* Place command on done queue. */
                  if (sp->request_sense_length == 0) {
                          ql_add_link_b(done_q, &sp->cmd);
!                         rsp_q->status_srb = NULL;
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_ip_entry
   *      Processes received ISP IP entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 2661,2687 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_entry(ql_adapter_state_t *ha, ip_entry_t *pkt23, ql_head_t *done_q,
!     uint32_t *set_flags, uint32_t *reset_flags)
  {
!         ql_srb_t        *sp;
          uint32_t        index, resp_identifier;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < MAX_OUTSTANDING_COMMANDS) {
                  /* the index seems reasonable */
!                 sp = ha->outstanding_cmds[index];
                  if (sp != NULL) {
!                         if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
--- 2801,2838 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, ip_entry_t *pkt23,
!     ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
  {
!         ql_srb_t        *sp = NULL;
          uint32_t        index, resp_identifier;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
!             &pkt23->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < ha->osc_max_cnt) {
                  /* the index seems reasonable */
!                 if ((sp = ha->outstanding_cmds[index]) == NULL) {
!                         sp = ql_verify_preprocessed_cmd(ha, rsp_q,
!                             (uint32_t *)&pkt23->handle,
!                             (uint32_t *)&resp_identifier, set_flags,
!                             reset_flags);
!                 }
                  if (sp != NULL) {
!                         if (sp == QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "QL_ABORTED_SRB handle=%xh\n",
!                                     resp_identifier);
!                                 sp = NULL;
!                                 ha->outstanding_cmds[index] = NULL;
!                         } else if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
*** 2688,2700 ****
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, sp->handle);
                                  sp = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
-                 } else {
-                         sp = ql_verify_preprocessed_cmd(ha,
-                             (uint32_t *)&pkt23->handle, set_flags, reset_flags);
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
--- 2839,2848 ----
*** 2702,2719 ****
  
          if (sp != NULL) {
                  tq = sp->lun_queue->target_queue;
  
                  /* Set ISP completion status */
!                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
                          ip_cmd_entry_t  *pkt24 = (ip_cmd_entry_t *)pkt23;
  
                          sp->pkt->pkt_reason = ddi_get16(
!                             ha->hba_buf.acc_handle, &pkt24->hdl_status);
                  } else {
                          sp->pkt->pkt_reason = ddi_get16(
!                             ha->hba_buf.acc_handle, &pkt23->comp_status);
                  }
  
                  if (ha->task_daemon_flags & LOOP_DOWN) {
                          EL(ha, "Loop Not Ready Retry, d_id=%xh\n",
                              tq->d_id.b24);
--- 2850,2867 ----
  
          if (sp != NULL) {
                  tq = sp->lun_queue->target_queue;
  
                  /* Set ISP completion status */
!                 if (CFG_IST(ha, CFG_CTRL_24XX)) {
                          ip_cmd_entry_t  *pkt24 = (ip_cmd_entry_t *)pkt23;
  
                          sp->pkt->pkt_reason = ddi_get16(
!                             rsp_q->rsp_ring.acc_handle, &pkt24->hdl_status);
                  } else {
                          sp->pkt->pkt_reason = ddi_get16(
!                             rsp_q->rsp_ring.acc_handle, &pkt23->comp_status);
                  }
  
                  if (ha->task_daemon_flags & LOOP_DOWN) {
                          EL(ha, "Loop Not Ready Retry, d_id=%xh\n",
                              tq->d_id.b24);
*** 2779,2797 ****
                  sp->flags |= SRB_ISP_COMPLETED;
  
                  ql_add_link_b(done_q, &sp->cmd);
  
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_ip_rcv_entry
   *      Processes received ISP IP buffers entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 2927,2946 ----
                  sp->flags |= SRB_ISP_COMPLETED;
  
                  ql_add_link_b(done_q, &sp->cmd);
  
          }
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_ip_rcv_entry
   *      Processes received ISP IP buffers entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 2798,2816 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_rcv_entry(ql_adapter_state_t *ha, ip_rcv_entry_t *pkt,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          port_id_t       s_id;
          uint16_t        index;
          uint8_t         cnt;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Locate device queue. */
          s_id.b.al_pa = pkt->s_id[0];
          s_id.b.area = pkt->s_id[1];
          s_id.b.domain = pkt->s_id[2];
--- 2947,2966 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_rcv_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     ip_rcv_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          port_id_t       s_id;
          uint16_t        index;
          uint8_t         cnt;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Locate device queue. */
          s_id.b.al_pa = pkt->s_id[0];
          s_id.b.area = pkt->s_id[1];
          s_id.b.domain = pkt->s_id[2];
*** 2817,2828 ****
          if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
                  EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
                  return;
          }
  
!         tq->ub_sequence_length = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
!             &pkt->seq_length);
          tq->ub_total_seg_cnt = pkt->segment_count;
          tq->ub_seq_id = ++ha->ub_seq_id;
          tq->ub_seq_cnt = 0;
          tq->ub_frame_ro = 0;
          tq->ub_loop_id = pkt->loop_id;
--- 2967,2978 ----
          if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
                  EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
                  return;
          }
  
!         tq->ub_sequence_length = (uint16_t)ddi_get16(
!             rsp_q->rsp_ring.acc_handle, &pkt->seq_length);
          tq->ub_total_seg_cnt = pkt->segment_count;
          tq->ub_seq_id = ++ha->ub_seq_id;
          tq->ub_seq_cnt = 0;
          tq->ub_frame_ro = 0;
          tq->ub_loop_id = pkt->loop_id;
*** 2829,2857 ****
          ha->rcv_dev_q = tq;
  
          for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt <
              tq->ub_total_seg_cnt; cnt++) {
  
!                 index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
                      &pkt->buffer_handle[cnt]);
  
                  if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
                          EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
                          *set_flags |= ISP_ABORT_NEEDED;
                          break;
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_ip_rcv_cont_entry
   *      Processes received ISP IP buffers continuation entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 2979,3008 ----
          ha->rcv_dev_q = tq;
  
          for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt <
              tq->ub_total_seg_cnt; cnt++) {
  
!                 index = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
                      &pkt->buffer_handle[cnt]);
  
                  if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
                          EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
                          *set_flags |= ISP_ABORT_NEEDED;
                          break;
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_ip_rcv_cont_entry
   *      Processes received ISP IP buffers continuation entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 2858,2903 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ip_rcv_cont_entry_t *pkt,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          uint16_t        index;
          uint8_t         cnt;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if ((tq = ha->rcv_dev_q) == NULL) {
                  EL(ha, "No IP receive device\n");
                  return;
          }
  
          for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES &&
              tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
  
!                 index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
                      &pkt->buffer_handle[cnt]);
  
                  if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
                          EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
                          *set_flags |= ISP_ABORT_NEEDED;
                          break;
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ip_rcv_24xx_entry_t
   *      Processes received ISP24xx IP buffers entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 3009,3056 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     ip_rcv_cont_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          uint16_t        index;
          uint8_t         cnt;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started\n");
  
          if ((tq = ha->rcv_dev_q) == NULL) {
                  EL(ha, "No IP receive device\n");
                  return;
          }
  
          for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES &&
              tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
  
!                 index = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
                      &pkt->buffer_handle[cnt]);
  
                  if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
                          EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
                          *set_flags |= ISP_ABORT_NEEDED;
                          break;
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ip_rcv_24xx_entry_t
   *      Processes received ISP24xx IP buffers entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 2904,2922 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ip_rcv_24xx_entry_t *pkt,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          port_id_t       s_id;
          uint16_t        index;
          uint8_t         cnt;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Locate device queue. */
          s_id.b.al_pa = pkt->s_id[0];
          s_id.b.area = pkt->s_id[1];
          s_id.b.domain = pkt->s_id[2];
--- 3057,3076 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     ip_rcv_24xx_entry_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          port_id_t       s_id;
          uint16_t        index;
          uint8_t         cnt;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Locate device queue. */
          s_id.b.al_pa = pkt->s_id[0];
          s_id.b.area = pkt->s_id[1];
          s_id.b.domain = pkt->s_id[2];
*** 2925,2965 ****
                  return;
          }
  
          if (tq->ub_total_seg_cnt == 0) {
                  tq->ub_sequence_length = (uint16_t)ddi_get16(
!                     ha->hba_buf.acc_handle, &pkt->seq_length);
                  tq->ub_total_seg_cnt = pkt->segment_count;
                  tq->ub_seq_id = ++ha->ub_seq_id;
                  tq->ub_seq_cnt = 0;
                  tq->ub_frame_ro = 0;
                  tq->ub_loop_id = (uint16_t)ddi_get16(
!                     ha->hba_buf.acc_handle, &pkt->n_port_hdl);
          }
  
          for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt <
              tq->ub_total_seg_cnt; cnt++) {
  
!                 index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
                      &pkt->buffer_handle[cnt]);
  
                  if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
                          EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
                          *set_flags |= ISP_ABORT_NEEDED;
                          break;
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_ms_entry
   *      Processes received Name/Management/CT Pass-Through entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt23:          entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 3079,3120 ----
                  return;
          }
  
          if (tq->ub_total_seg_cnt == 0) {
                  tq->ub_sequence_length = (uint16_t)ddi_get16(
!                     rsp_q->rsp_ring.acc_handle, &pkt->seq_length);
                  tq->ub_total_seg_cnt = pkt->segment_count;
                  tq->ub_seq_id = ++ha->ub_seq_id;
                  tq->ub_seq_cnt = 0;
                  tq->ub_frame_ro = 0;
                  tq->ub_loop_id = (uint16_t)ddi_get16(
!                     rsp_q->rsp_ring.acc_handle, &pkt->n_port_hdl);
          }
  
          for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt <
              tq->ub_total_seg_cnt; cnt++) {
  
!                 index = (uint16_t)ddi_get16(rsp_q->rsp_ring.acc_handle,
                      &pkt->buffer_handle[cnt]);
  
                  if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
                          EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
                          *set_flags |= ISP_ABORT_NEEDED;
                          break;
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_ms_entry
   *      Processes received Name/Management/CT Pass-Through entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt23:          entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 2966,2993 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ms_entry(ql_adapter_state_t *ha, ms_entry_t *pkt23, ql_head_t *done_q,
!     uint32_t *set_flags, uint32_t *reset_flags)
  {
!         ql_srb_t                *sp;
          uint32_t                index, cnt, resp_identifier;
          ql_tgt_t                *tq;
          ct_passthru_entry_t     *pkt24 = (ct_passthru_entry_t *)pkt23;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < MAX_OUTSTANDING_COMMANDS) {
                  /* the index seems reasonable */
!                 sp = ha->outstanding_cmds[index];
                  if (sp != NULL) {
!                         if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
--- 3121,3159 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_ms_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q, ms_entry_t *pkt23,
!     ql_head_t *done_q, uint64_t *set_flags, uint64_t *reset_flags)
  {
!         ql_srb_t                *sp = NULL;
          uint32_t                index, cnt, resp_identifier;
          ql_tgt_t                *tq;
          ct_passthru_entry_t     *pkt24 = (ct_passthru_entry_t *)pkt23;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle,
!             &pkt23->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < ha->osc_max_cnt) {
                  /* the index seems reasonable */
!                 if ((sp = ha->outstanding_cmds[index]) == NULL) {
!                         sp = ql_verify_preprocessed_cmd(ha, rsp_q,
!                             (uint32_t *)&pkt23->handle,
!                             (uint32_t *)&resp_identifier, set_flags,
!                             reset_flags);
!                 }
                  if (sp != NULL) {
!                         if (sp == QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "QL_ABORTED_SRB handle=%xh\n",
!                                     resp_identifier);
!                                 sp = NULL;
!                                 ha->outstanding_cmds[index] = NULL;
!                         } else if (sp->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
*** 2994,3006 ****
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, sp->handle);
                                  sp = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
-                 } else {
-                         sp = ql_verify_preprocessed_cmd(ha,
-                             (uint32_t *)&pkt23->handle, set_flags, reset_flags);
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
--- 3160,3169 ----
*** 3015,3030 ****
                  }
  
                  tq = sp->lun_queue->target_queue;
  
                  /* Set ISP completion status */
!                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
                          sp->pkt->pkt_reason = ddi_get16(
!                             ha->hba_buf.acc_handle, &pkt24->status);
                  } else {
                          sp->pkt->pkt_reason = ddi_get16(
!                             ha->hba_buf.acc_handle, &pkt23->comp_status);
                  }
  
                  if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE &&
                      sp->retry_count) {
                          EL(ha, "Resouce Unavailable Retry = %d\n",
--- 3178,3193 ----
                  }
  
                  tq = sp->lun_queue->target_queue;
  
                  /* Set ISP completion status */
!                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                          sp->pkt->pkt_reason = ddi_get16(
!                             rsp_q->rsp_ring.acc_handle, &pkt24->status);
                  } else {
                          sp->pkt->pkt_reason = ddi_get16(
!                             rsp_q->rsp_ring.acc_handle, &pkt23->comp_status);
                  }
  
                  if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE &&
                      sp->retry_count) {
                          EL(ha, "Resouce Unavailable Retry = %d\n",
*** 3083,3117 ****
                          EL(ha, "Reset Retry\n");
  
                          /* Set retry status. */
                          sp->flags |= SRB_RETRY;
  
!                 } else if (CFG_IST(ha, CFG_CTRL_24258081) &&
                      sp->pkt->pkt_reason == CS_DATA_UNDERRUN) {
!                         cnt = ddi_get32(ha->hba_buf.acc_handle,
                              &pkt24->resp_byte_count);
                          if (cnt < sizeof (fc_ct_header_t)) {
                                  EL(ha, "Data underrun\n");
                          } else {
                                  sp->pkt->pkt_reason = CS_COMPLETE;
                          }
  
                  } else if (sp->pkt->pkt_reason != CS_COMPLETE) {
                          EL(ha, "status err=%xh\n", sp->pkt->pkt_reason);
                  }
  
                  if (sp->pkt->pkt_reason == CS_COMPLETE) {
                          /*EMPTY*/
!                         QL_PRINT_3(CE_CONT, "(%d): ct_cmdrsp=%x%02xh resp\n",
!                             ha->instance, sp->pkt->pkt_cmd[8],
!                             sp->pkt->pkt_cmd[9]);
                          QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen);
                  }
  
                  /* For nameserver restore command, management change header. */
                  if ((sp->flags & SRB_RETRY) == 0) {
!                         tq->d_id.b24 == 0xfffffc ?
                              ql_cthdr_endian(sp->pkt->pkt_cmd_acc,
                              sp->pkt->pkt_cmd, B_TRUE) :
                              ql_cthdr_endian(sp->pkt->pkt_resp_acc,
                              sp->pkt->pkt_resp, B_TRUE);
                  }
--- 3246,3287 ----
                          EL(ha, "Reset Retry\n");
  
                          /* Set retry status. */
                          sp->flags |= SRB_RETRY;
  
!                 } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
                      sp->pkt->pkt_reason == CS_DATA_UNDERRUN) {
!                         cnt = ddi_get32(rsp_q->rsp_ring.acc_handle,
                              &pkt24->resp_byte_count);
                          if (cnt < sizeof (fc_ct_header_t)) {
                                  EL(ha, "Data underrun\n");
                          } else {
                                  sp->pkt->pkt_reason = CS_COMPLETE;
                          }
  
+                 } else if (sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE ||
+                     sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT) {
+                         EL(ha, "Port unavailable %xh\n", sp->pkt->pkt_reason);
+                         DEVICE_QUEUE_LOCK(tq);
+                         tq->flags |= TQF_LOGIN_NEEDED;
+                         DEVICE_QUEUE_UNLOCK(tq);
+                         sp->pkt->pkt_reason = CS_TIMEOUT;
+ 
                  } else if (sp->pkt->pkt_reason != CS_COMPLETE) {
                          EL(ha, "status err=%xh\n", sp->pkt->pkt_reason);
                  }
  
                  if (sp->pkt->pkt_reason == CS_COMPLETE) {
                          /*EMPTY*/
!                         QL_PRINT_3(ha, "ct_cmdrsp=%x%02xh resp\n",
!                             sp->pkt->pkt_cmd[8], sp->pkt->pkt_cmd[9]);
                          QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen);
                  }
  
                  /* For nameserver restore command, management change header. */
                  if ((sp->flags & SRB_RETRY) == 0) {
!                         tq->d_id.b24 == FS_NAME_SERVER ?
                              ql_cthdr_endian(sp->pkt->pkt_cmd_acc,
                              sp->pkt->pkt_cmd, B_TRUE) :
                              ql_cthdr_endian(sp->pkt->pkt_resp_acc,
                              sp->pkt->pkt_resp, B_TRUE);
                  }
*** 3121,3139 ****
  
                  /* Place command on done queue. */
                  ql_add_link_b(done_q, &sp->cmd);
  
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_report_id_entry
   *      Processes received Name/Management/CT Pass-Through entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 3291,3310 ----
  
                  /* Place command on done queue. */
                  ql_add_link_b(done_q, &sp->cmd);
  
          }
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_report_id_entry
   *      Processes received Name/Management/CT Pass-Through entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt:            entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 3140,3188 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_report_id_entry(ql_adapter_state_t *ha, report_id_1_t *pkt,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         EL(ha, "format=%d, vp=%d, status=%d\n",
!             pkt->format, pkt->vp_index, pkt->status);
  
          if (pkt->format == 1) {
                  /* Locate port state structure. */
                  for (vha = ha; vha != NULL; vha = vha->vp_next) {
                          if (vha->vp_index == pkt->vp_index) {
                                  break;
                          }
                  }
!                 if (vha != NULL && vha->vp_index != 0 &&
!                     (pkt->status == CS_COMPLETE ||
!                     pkt->status == CS_PORT_ID_CHANGE)) {
                          *set_flags |= LOOP_RESYNC_NEEDED;
                          *reset_flags &= ~LOOP_RESYNC_NEEDED;
!                         vha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
                          TASK_DAEMON_LOCK(ha);
!                         vha->task_daemon_flags |= LOOP_RESYNC_NEEDED;
                          vha->task_daemon_flags &= ~LOOP_DOWN;
                          TASK_DAEMON_UNLOCK(ha);
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_els_entry
   *      Processes received ELS Pass-Through entry.
   *
   * Input:
   *      ha:             adapter state pointer.
   *      pkt23:          entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
--- 3311,3390 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_report_id_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     report_id_acq_t *pkt, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(ha, "started\n");
  
!         EL(ha, "format=%d, index=%d, status=%d\n",
!             pkt->format, pkt->vp_index, pkt->vp_status);
  
          if (pkt->format == 1) {
                  /* Locate port state structure. */
                  for (vha = ha; vha != NULL; vha = vha->vp_next) {
                          if (vha->vp_index == pkt->vp_index) {
                                  break;
                          }
                  }
!                 if (vha != NULL) {
!                         if (pkt->vp_status == CS_COMPLETE ||
!                             pkt->vp_status == CS_PORT_ID_CHANGE) {
!                                 if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
!                                         vha->fcoe_fcf_idx = pkt->fcf_index;
!                                 }
!                                 if (vha->vp_index != 0) {
                                          *set_flags |= LOOP_RESYNC_NEEDED;
                                          *reset_flags &= ~LOOP_RESYNC_NEEDED;
!                                         vha->loop_down_timer =
!                                             LOOP_DOWN_TIMER_OFF;
                                          TASK_DAEMON_LOCK(ha);
!                                         vha->task_daemon_flags |=
!                                             LOOP_RESYNC_NEEDED;
                                          vha->task_daemon_flags &= ~LOOP_DOWN;
                                          TASK_DAEMON_UNLOCK(ha);
                                  }
+                                 ADAPTER_STATE_LOCK(ha);
+                                 vha->flags &= ~VP_ID_NOT_ACQUIRED;
+                                 ADAPTER_STATE_UNLOCK(ha);
+                         } else {
+                                 /* FA-WWPN failure. */
+                                 if (pkt->vp_status == CS_INCOMPLETE &&
+                                     pkt->ls_rjt_reason_code == 0xff &&
+                                     pkt->ls_rjt_explanation == 0x44) {
+                                         *set_flags |= ISP_ABORT_NEEDED;
                                  }
+                                 if (CFG_IST(ha, CFG_FCOE_SUPPORT)) {
+                                         EL(ha, "sts sc=%d, rjt_rea=%xh, "
+                                             "rjt_exp=%xh, rjt_sc=%xh\n",
+                                             pkt->status_subcode,
+                                             pkt->ls_rjt_reason_code,
+                                             pkt->ls_rjt_explanation,
+                                             pkt->ls_rjt_subcode);
+                                 }
+                                 ADAPTER_STATE_LOCK(ha);
+                                 vha->flags |= VP_ID_NOT_ACQUIRED;
+                                 ADAPTER_STATE_UNLOCK(ha);
+                         }
+                 }
+         }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_els_entry
   *      Processes received ELS Pass-Through entry.
   *
   * Input:
   *      ha:             adapter state pointer.
+  *      rsp_q:          response queue structure pointer.
   *      pkt23:          entry pointer.
   *      done_q:         done queue pointer.
   *      set_flags:      task daemon flags to set.
   *      reset_flags:    task daemon flags to reset.
   *
*** 3189,3216 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_els_passthru_entry(ql_adapter_state_t *ha, els_passthru_entry_rsp_t *rsp,
!     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
  {
          ql_tgt_t        *tq;
!         port_id_t       d_id, s_id;
!         ql_srb_t        *srb;
          uint32_t        index, resp_identifier;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &rsp->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < MAX_OUTSTANDING_COMMANDS) {
                  /* the index seems reasonable */
!                 srb = ha->outstanding_cmds[index];
                  if (srb != NULL) {
!                         if (srb->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  srb->handle = 0;
                                  srb->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
--- 3391,3429 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  /* ARGSUSED */
  static void
! ql_els_passthru_entry(ql_adapter_state_t *ha, ql_response_q_t *rsp_q,
!     els_passthru_entry_rsp_t *rsp, ql_head_t *done_q, uint64_t *set_flags,
!     uint64_t *reset_flags)
  {
          ql_tgt_t        *tq;
!         port_id_t       s_id;
!         ql_srb_t        *srb = NULL;
          uint32_t        index, resp_identifier;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Validate the response entry handle. */
!         resp_identifier = ddi_get32(rsp_q->rsp_ring.acc_handle, &rsp->handle);
          index = resp_identifier & OSC_INDEX_MASK;
!         if (index < ha->osc_max_cnt) {
                  /* the index seems reasonable */
!                 if ((srb = ha->outstanding_cmds[index]) == NULL) {
!                         srb = ql_verify_preprocessed_cmd(ha, rsp_q,
!                             (uint32_t *)&rsp->handle,
!                             (uint32_t *)&resp_identifier, set_flags,
!                             reset_flags);
!                 }
                  if (srb != NULL) {
!                         if (srb == QL_ABORTED_SRB(ha)) {
!                                 EL(ha, "QL_ABORTED_SRB handle=%xh\n",
!                                     resp_identifier);
!                                 srb = NULL;
!                                 ha->outstanding_cmds[index] = NULL;
!                         } else if (srb->handle == resp_identifier) {
                                  /* Neo, you're the one... */
                                  ha->outstanding_cmds[index] = NULL;
                                  srb->handle = 0;
                                  srb->flags &= ~SRB_IN_TOKEN_ARRAY;
                          } else {
*** 3217,3255 ****
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, srb->handle);
                                  srb = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
-                 } else {
-                         srb = ql_verify_preprocessed_cmd(ha,
-                             (uint32_t *)&rsp->handle, set_flags, reset_flags);
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
          }
  
          if (srb != NULL) {
                  if (!(srb->flags & SRB_ELS_PKT)) {
!                         EL(ha, "Not SRB_ELS_PKT flags=%xh, isp_abort_needed",
                              srb->flags);
                          *set_flags |= ISP_ABORT_NEEDED;
                          return;
                  }
  
                  (void) ddi_dma_sync(srb->pkt->pkt_resp_dma, 0, 0,
                      DDI_DMA_SYNC_FORKERNEL);
  
                  /* Set ISP completion status */
!                 srb->pkt->pkt_reason = ddi_get16(
!                     ha->hba_buf.acc_handle, &rsp->comp_status);
  
                  if (srb->pkt->pkt_reason != CS_COMPLETE) {
                          la_els_rjt_t    rjt;
-                         EL(ha, "status err=%xh\n", srb->pkt->pkt_reason);
  
                          if (srb->pkt->pkt_reason == CS_LOGIN_LOGOUT_ERROR) {
                                  EL(ha, "e1=%xh e2=%xh\n",
                                      rsp->error_subcode1, rsp->error_subcode2);
                          }
  
--- 3430,3467 ----
                                  EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
                                      resp_identifier, srb->handle);
                                  srb = NULL;
                                  ql_signal_abort(ha, set_flags);
                          }
                  }
          } else {
                  EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
                      index, resp_identifier);
                  ql_signal_abort(ha, set_flags);
          }
  
          if (srb != NULL) {
                  if (!(srb->flags & SRB_ELS_PKT)) {
!                         EL(ha, "Not SRB_ELS_PKT flags=%xh, isp_abort_needed\n",
                              srb->flags);
                          *set_flags |= ISP_ABORT_NEEDED;
                          return;
                  }
  
                  (void) ddi_dma_sync(srb->pkt->pkt_resp_dma, 0, 0,
                      DDI_DMA_SYNC_FORKERNEL);
  
                  /* Set ISP completion status */
!                 srb->pkt->pkt_reason = ddi_get16(rsp_q->rsp_ring.acc_handle,
!                     &rsp->comp_status);
  
                  if (srb->pkt->pkt_reason != CS_COMPLETE) {
                          la_els_rjt_t    rjt;
  
+                         EL(ha, "srb=%ph,status err=%xh\n",
+                             srb, srb->pkt->pkt_reason);
+ 
                          if (srb->pkt->pkt_reason == CS_LOGIN_LOGOUT_ERROR) {
                                  EL(ha, "e1=%xh e2=%xh\n",
                                      rsp->error_subcode1, rsp->error_subcode2);
                          }
  
*** 3272,3306 ****
                          uint16_t        loop_id;
  
                          /* Indicate ISP completion */
                          srb->flags |= SRB_ISP_COMPLETED;
  
!                         loop_id = ddi_get16(ha->hba_buf.acc_handle,
                              &rsp->n_port_hdl);
  
!                         if (ha->topology & QL_N_PORT) {
!                                 /* create a target Q if there isn't one */
!                                 tq = ql_loop_id_to_queue(ha, loop_id);
!                                 if (tq == NULL) {
!                                         d_id.b.al_pa = rsp->d_id_7_0;
!                                         d_id.b.area = rsp->d_id_15_8;
!                                         d_id.b.domain = rsp->d_id_23_16;
!                                         /* Acquire adapter state lock. */
!                                         ADAPTER_STATE_LOCK(ha);
  
!                                         tq = ql_dev_init(ha, d_id, loop_id);
!                                         EL(ha, " tq = %x\n", tq);
! 
!                                         ADAPTER_STATE_UNLOCK(ha);
!                                 }
! 
                                  /* on plogi success assume the chosen s_id */
!                                 opcode = ddi_get8(ha->hba_buf.acc_handle,
                                      &rsp->els_cmd_opcode);
  
!                                 EL(ha, "els_cmd_opcode=%x srb->pkt=%x\n",
!                                     opcode, srb->pkt);
  
                                  if (opcode == LA_ELS_PLOGI) {
                                          s_id.b.al_pa = rsp->s_id_7_0;
                                          s_id.b.area = rsp->s_id_15_8;
                                          s_id.b.domain = rsp->s_id_23_16;
--- 3484,3508 ----
                          uint16_t        loop_id;
  
                          /* Indicate ISP completion */
                          srb->flags |= SRB_ISP_COMPLETED;
  
!                         loop_id = ddi_get16(rsp_q->rsp_ring.acc_handle,
                              &rsp->n_port_hdl);
  
!                         /* tq is obtained from lun_queue */
!                         tq = srb->lun_queue->target_queue;
  
!                         if (ha->topology & QL_N_PORT) {
                                  /* on plogi success assume the chosen s_id */
!                                 opcode = ddi_get8(rsp_q->rsp_ring.acc_handle,
                                      &rsp->els_cmd_opcode);
  
!                                 EL(ha, "els opcode=%x srb=%ph,pkt=%ph, tq=%ph"
!                                     ", portid=%xh, tqlpid=%xh, loop_id=%xh\n",
!                                     opcode, srb, srb->pkt, tq, tq->d_id.b24,
!                                     tq->loop_id, loop_id);
  
                                  if (opcode == LA_ELS_PLOGI) {
                                          s_id.b.al_pa = rsp->s_id_7_0;
                                          s_id.b.area = rsp->s_id_15_8;
                                          s_id.b.domain = rsp->s_id_23_16;
*** 3318,3337 ****
  
                          if (tq != NULL) {
                                  tq->logout_sent = 0;
                                  tq->flags &= ~TQF_NEED_AUTHENTICATION;
  
!                                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
                                          tq->flags |= TQF_IIDMA_NEEDED;
                                  }
                          srb->pkt->pkt_state = FC_PKT_SUCCESS;
                          }
                  }
                  /* invoke the callback */
!                 ql_awaken_task_daemon(ha, srb, 0, 0);
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_signal_abort
   *      Signal to the task daemon that a condition warranting an
--- 3520,3550 ----
  
                          if (tq != NULL) {
                                  tq->logout_sent = 0;
                                  tq->flags &= ~TQF_NEED_AUTHENTICATION;
  
!                                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                                          tq->flags |= TQF_IIDMA_NEEDED;
                                  }
                                  srb->pkt->pkt_state = FC_PKT_SUCCESS;
                          }
                  }
+ 
+                 /* Remove command from watchdog queue. */
+                 if (srb->flags & SRB_WATCHDOG_ENABLED) {
+                         tq = srb->lun_queue->target_queue;
+ 
+                         DEVICE_QUEUE_LOCK(tq);
+                         ql_remove_link(&tq->wdg, &srb->wdg);
+                         srb->flags &= ~SRB_WATCHDOG_ENABLED;
+                         DEVICE_QUEUE_UNLOCK(tq);
+                 }
+ 
                  /* invoke the callback */
!                 ql_io_comp(srb);
          }
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_signal_abort
   *      Signal to the task daemon that a condition warranting an
*** 3343,3354 ****
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags)
  {
!         if (!CFG_IST(ha, CFG_CTRL_8021) &&
              !(ha->task_daemon_flags & (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
                  *set_flags |= ISP_ABORT_NEEDED;
          }
  }
--- 3556,3567 ----
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static void
! ql_signal_abort(ql_adapter_state_t *ha, uint64_t *set_flags)
  {
!         if (!CFG_IST(ha, CFG_CTRL_82XX) &&
              !(ha->task_daemon_flags & (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
                  *set_flags |= ISP_ABORT_NEEDED;
          }
  }