fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / scsi / qla2xxx / qla_isr.c
index 415242a..39fd17b 100644 (file)
@@ -1,62 +1,41 @@
 /*
- *                  QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP2x00 device driver for Linux 2.6.x
- * Copyright (C) 2003-2004 QLogic Corporation
- * (www.qlogic.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2005 QLogic Corporation
  *
+ * See LICENSE.qla2xxx for copyright and licensing details.
  */
-
-#include "qla_os.h"
-
 #include "qla_def.h"
 
+#include <scsi/scsi_tcq.h>
+
 static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
-static void qla2x00_async_event(scsi_qla_host_t *, uint32_t);
+static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
 static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
-void qla2x00_process_response_queue(struct scsi_qla_host *);
-static void qla2x00_status_entry(scsi_qla_host_t *, sts_entry_t *);
+static void qla2x00_status_entry(scsi_qla_host_t *, void *);
 static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
 static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
 static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
 
-static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *);
+static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
 
 /**
- * qla2x00_intr_handler() - Process interrupts for the ISP.
+ * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
  * @irq:
  * @dev_id: SCSI driver HA context
- * @regs:
  *
  * Called by system whenever the host adapter generates an interrupt.
  *
  * Returns handled flag.
  */
 irqreturn_t
-qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+qla2100_intr_handler(int irq, void *dev_id)
 {
        scsi_qla_host_t *ha;
-       device_reg_t    *reg;
-       uint32_t        mbx;
-       int             status = 0;
-       unsigned long   flags = 0;
-       unsigned long   mbx_flags = 0;
-       unsigned long   intr_iter;
-       uint32_t        stat;
-       uint16_t        hccr;
-
-       /* Don't loop forever, interrupt are OFF */
-       intr_iter = 50; 
+       struct device_reg_2xxx __iomem *reg;
+       int             status;
+       unsigned long   flags;
+       unsigned long   iter;
+       uint16_t        mb[4];
 
        ha = (scsi_qla_host_t *) dev_id;
        if (!ha) {
@@ -65,158 +44,167 @@ qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
                return (IRQ_NONE);
        }
 
-       reg = ha->iobase;
+       reg = &ha->iobase->isp;
+       status = 0;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
-
-       for (;;) {
-               /* Relax CPU! */
-               if (!(intr_iter--))
+       for (iter = 50; iter--; ) {
+               if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
                        break;
 
-               if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
-                       if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
-                               break;
+               if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
+                       WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
+                       RD_REG_WORD(&reg->hccr);
 
-                       if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
-                               WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
-                               RD_REG_WORD(&reg->hccr);
-
-                               /* Get mailbox data. */
-                               mbx = RD_MAILBOX_REG(ha, reg, 0);
-                               if (mbx > 0x3fff && mbx < 0x8000) {
-                                       qla2x00_mbx_completion(ha,
-                                           (uint16_t)mbx);
-                                       status |= MBX_INTERRUPT;
-                               } else if (mbx > 0x7fff && mbx < 0xc000) {
-                                       qla2x00_async_event(ha, mbx);
-                               } else {
-                                       /*EMPTY*/
-                                       DEBUG2(printk("scsi(%ld): Unrecognized "
-                                           "interrupt type (%d)\n",
-                                           ha->host_no, mbx));
-                               }
-                               /* Release mailbox registers. */
-                               WRT_REG_WORD(&reg->semaphore, 0);
-                               /* Workaround for ISP2100 chip. */
-                               if (IS_QLA2100(ha))
-                                       RD_REG_WORD(&reg->semaphore);
+                       /* Get mailbox data. */
+                       mb[0] = RD_MAILBOX_REG(ha, reg, 0);
+                       if (mb[0] > 0x3fff && mb[0] < 0x8000) {
+                               qla2x00_mbx_completion(ha, mb[0]);
+                               status |= MBX_INTERRUPT;
+                       } else if (mb[0] > 0x7fff && mb[0] < 0xc000) {
+                               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
+                               mb[2] = RD_MAILBOX_REG(ha, reg, 2);
+                               mb[3] = RD_MAILBOX_REG(ha, reg, 3);
+                               qla2x00_async_event(ha, mb);
                        } else {
-                               qla2x00_process_response_queue(ha);
-       
-                               WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
-                               RD_REG_WORD(&reg->hccr);
+                               /*EMPTY*/
+                               DEBUG2(printk("scsi(%ld): Unrecognized "
+                                   "interrupt type (%d).\n",
+                                   ha->host_no, mb[0]));
                        }
-               } else /* IS_QLA23XX(ha) */ {
-                       stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
-                       if ((stat & HSR_RISC_INT) == 0)
-                               break;
-
-                       mbx = MSW(stat);
-                       switch (stat & 0xff) {
-                       case 0x13:
-                               qla2x00_process_response_queue(ha);
-                               break;
-                       case 0x1:
-                       case 0x2:
-                       case 0x10:
-                       case 0x11:
-                               qla2x00_mbx_completion(ha, (uint16_t)mbx);
-                               status |= MBX_INTERRUPT;
+                       /* Release mailbox registers. */
+                       WRT_REG_WORD(&reg->semaphore, 0);
+                       RD_REG_WORD(&reg->semaphore);
+               } else {
+                       qla2x00_process_response_queue(ha);
 
-                               /* Release mailbox registers. */
-                               WRT_REG_WORD(&reg->semaphore, 0);
-                               break;
-                       case 0x12:
-                               qla2x00_async_event(ha, mbx);
-                               break;
-                       case 0x15:
-                               mbx = mbx << 16 | MBA_CMPLT_1_16BIT;
-                               qla2x00_async_event(ha, mbx);
-                               break;
-                       case 0x16:
-                               mbx = mbx << 16 | MBA_SCSI_COMPLETION;
-                               qla2x00_async_event(ha, mbx);
-                               break;
-                       default:
-                               hccr = RD_REG_WORD(&reg->hccr);
-                               if (hccr & HCCR_RISC_PAUSE) {
-                                       qla_printk(KERN_INFO, ha,
-                                           "RISC paused, dumping HCCR=%x\n",
-                                           hccr);
-
-                                       /*
-                                        * Issue a "HARD" reset in order for
-                                        * the RISC interrupt bit to be
-                                        * cleared.  Schedule a big hammmer to
-                                        * get out of the RISC PAUSED state.
-                                        */
-                                       WRT_REG_WORD(&reg->hccr,
-                                           HCCR_RESET_RISC);
-                                       RD_REG_WORD(&reg->hccr);
-                                       set_bit(ISP_ABORT_NEEDED,
-                                           &ha->dpc_flags);
-                                       break;
-                               } else {
-                                       DEBUG2(printk("scsi(%ld): Unrecognized "
-                                           "interrupt type (%d)\n",
-                                           ha->host_no, stat & 0xff));
-                               }
-                               break;
-                       }
                        WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
                        RD_REG_WORD(&reg->hccr);
                }
        }
-
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-       qla2x00_next(ha);
-       ha->last_irq_cpu = smp_processor_id();
-       ha->total_isr_cnt++;
-
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+               spin_lock_irqsave(&ha->mbx_reg_lock, flags);
 
-               /* There was a mailbox completion */
-               DEBUG3(printk("%s(%ld): Going to get mbx reg lock.\n",
-                   __func__, ha->host_no));
+               set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+               up(&ha->mbx_intr_sem);
 
-               spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
+               spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
+       }
 
-               if (ha->mcp == NULL) {
-                       DEBUG3(printk("%s(%ld): Error mbx pointer.\n",
-                           __func__, ha->host_no));
-               } else {
-                       DEBUG3(printk("%s(%ld): Going to set mbx intr flags. "
-                           "cmd=%x.\n",
-                           __func__, ha->host_no, ha->mcp->mb[0]));
-               }
-               set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+       return (IRQ_HANDLED);
+}
 
-               DEBUG3(printk("%s(%ld): Going to wake up mbx function for "
-                   "completion.\n",
-                   __func__, ha->host_no));
+/**
+ * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
+ * @irq:
+ * @dev_id: SCSI driver HA context
+ *
+ * Called by system whenever the host adapter generates an interrupt.
+ *
+ * Returns handled flag.
+ */
+irqreturn_t
+qla2300_intr_handler(int irq, void *dev_id)
+{
+       scsi_qla_host_t *ha;
+       struct device_reg_2xxx __iomem *reg;
+       int             status;
+       unsigned long   flags;
+       unsigned long   iter;
+       uint32_t        stat;
+       uint16_t        hccr;
+       uint16_t        mb[4];
 
-               up(&ha->mbx_intr_sem);
+       ha = (scsi_qla_host_t *) dev_id;
+       if (!ha) {
+               printk(KERN_INFO
+                   "%s(): NULL host pointer\n", __func__);
+               return (IRQ_NONE);
+       }
 
-               DEBUG3(printk("%s(%ld): Going to release mbx reg lock.\n",
-                   __func__, ha->host_no));
+       reg = &ha->iobase->isp;
+       status = 0;
 
-               spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags);
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       for (iter = 50; iter--; ) {
+               stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
+               if (stat & HSR_RISC_PAUSED) {
+                       hccr = RD_REG_WORD(&reg->hccr);
+                       if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
+                               qla_printk(KERN_INFO, ha, "Parity error -- "
+                                   "HCCR=%x, Dumping firmware!\n", hccr);
+                       else
+                               qla_printk(KERN_INFO, ha, "RISC paused -- "
+                                   "HCCR=%x, Dumping firmware!\n", hccr);
+
+                       /*
+                        * Issue a "HARD" reset in order for the RISC
+                        * interrupt bit to be cleared.  Schedule a big
+                        * hammmer to get out of the RISC PAUSED state.
+                        */
+                       WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
+                       RD_REG_WORD(&reg->hccr);
+
+                       ha->isp_ops.fw_dump(ha, 1);
+                       set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+                       break;
+               } else if ((stat & HSR_RISC_INT) == 0)
+                       break;
+
+               switch (stat & 0xff) {
+               case 0x1:
+               case 0x2:
+               case 0x10:
+               case 0x11:
+                       qla2x00_mbx_completion(ha, MSW(stat));
+                       status |= MBX_INTERRUPT;
+
+                       /* Release mailbox registers. */
+                       WRT_REG_WORD(&reg->semaphore, 0);
+                       break;
+               case 0x12:
+                       mb[0] = MSW(stat);
+                       mb[1] = RD_MAILBOX_REG(ha, reg, 1);
+                       mb[2] = RD_MAILBOX_REG(ha, reg, 2);
+                       mb[3] = RD_MAILBOX_REG(ha, reg, 3);
+                       qla2x00_async_event(ha, mb);
+                       break;
+               case 0x13:
+                       qla2x00_process_response_queue(ha);
+                       break;
+               case 0x15:
+                       mb[0] = MBA_CMPLT_1_16BIT;
+                       mb[1] = MSW(stat);
+                       qla2x00_async_event(ha, mb);
+                       break;
+               case 0x16:
+                       mb[0] = MBA_SCSI_COMPLETION;
+                       mb[1] = MSW(stat);
+                       mb[2] = RD_MAILBOX_REG(ha, reg, 2);
+                       qla2x00_async_event(ha, mb);
+                       break;
+               default:
+                       DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
+                           "(%d).\n",
+                           ha->host_no, stat & 0xff));
+                       break;
+               }
+               WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
+               RD_REG_WORD_RELAXED(&reg->hccr);
        }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-       if (!list_empty(&ha->done_queue))
-               qla2x00_done(ha);
+       if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+           (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+               spin_lock_irqsave(&ha->mbx_reg_lock, flags);
 
-       /* Wakeup the DPC routine */
-       if ((!ha->flags.mbox_busy &&
-           (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
-               test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
-               test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) &&
-                   ha->dpc_wait && !ha->dpc_active) {
+               set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+               up(&ha->mbx_intr_sem);
 
-               up(ha->dpc_wait);
+               spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
        }
 
        return (IRQ_HANDLED);
@@ -231,22 +219,22 @@ static void
 qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
 {
        uint16_t        cnt;
-       uint16_t        *wptr;
-       device_reg_t    *reg = ha->iobase;
+       uint16_t __iomem *wptr;
+       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
        /* Load return mailbox registers. */
-       ha->flags.mbox_int = TRUE;
+       ha->flags.mbox_int = 1;
        ha->mailbox_out[0] = mb0;
-       wptr = (uint16_t *)MAILBOX_REG(ha, reg, 1);
+       wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1);
 
        for (cnt = 1; cnt < ha->mbx_count; cnt++) {
-               if (IS_QLA2200(ha) && cnt == 8) 
-                       wptr = (uint16_t *)MAILBOX_REG(ha, reg, 8);
+               if (IS_QLA2200(ha) && cnt == 8)
+                       wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8);
                if (cnt == 4 || cnt == 5)
                        ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr);
                else
                        ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
-       
+
                wptr++;
        }
 
@@ -262,78 +250,65 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
 /**
  * qla2x00_async_event() - Process aynchronous events.
  * @ha: SCSI driver HA context
- * @mb0: Mailbox0 register
+ * @mb: Mailbox registers (0 - 3)
  */
 static void
-qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
+qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 {
-       static char     *link_speeds[5] = { "1", "2", "4", "?", "10" };
+#define LS_UNKNOWN     2
+       static char     *link_speeds[5] = { "1", "2", "?", "4", "10" };
        char            *link_speed;
-       uint16_t        mb[4];
        uint16_t        handle_cnt;
        uint16_t        cnt;
        uint32_t        handles[5];
-       device_reg_t    *reg = ha->iobase;
+       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
        uint32_t        rscn_entry, host_pid;
        uint8_t         rscn_queue_index;
 
        /* Setup to process RIO completion. */
        handle_cnt = 0;
-       mb[0] = LSW(mbx);
        switch (mb[0]) {
        case MBA_SCSI_COMPLETION:
-               if (IS_QLA2100(ha) || IS_QLA2200(ha))
-                       handles[0] = le32_to_cpu(
-                           ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) |
-                           RD_MAILBOX_REG(ha, reg, 1));
-               else
-                       handles[0] = le32_to_cpu(
-                           ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) |
-                           MSW(mbx));
+               handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
                handle_cnt = 1;
                break;
        case MBA_CMPLT_1_16BIT:
-               if (IS_QLA2100(ha) || IS_QLA2200(ha))
-                       handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
-               else
-                       handles[0] = MSW(mbx);
+               handles[0] = mb[1];
                handle_cnt = 1;
                mb[0] = MBA_SCSI_COMPLETION;
                break;
        case MBA_CMPLT_2_16BIT:
-               handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
-               handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
+               handles[0] = mb[1];
+               handles[1] = mb[2];
                handle_cnt = 2;
                mb[0] = MBA_SCSI_COMPLETION;
                break;
        case MBA_CMPLT_3_16BIT:
-               handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
-               handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
-               handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3);
+               handles[0] = mb[1];
+               handles[1] = mb[2];
+               handles[2] = mb[3];
                handle_cnt = 3;
                mb[0] = MBA_SCSI_COMPLETION;
                break;
        case MBA_CMPLT_4_16BIT:
-               handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
-               handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
-               handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3);
+               handles[0] = mb[1];
+               handles[1] = mb[2];
+               handles[2] = mb[3];
                handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
                handle_cnt = 4;
                mb[0] = MBA_SCSI_COMPLETION;
                break;
        case MBA_CMPLT_5_16BIT:
-               handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1);
-               handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2);
-               handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3);
+               handles[0] = mb[1];
+               handles[1] = mb[2];
+               handles[2] = mb[3];
                handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
                handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7);
                handle_cnt = 5;
                mb[0] = MBA_SCSI_COMPLETION;
                break;
        case MBA_CMPLT_2_32BIT:
-               handles[0] = le32_to_cpu(
-                   ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) |
-                   RD_MAILBOX_REG(ha, reg, 1));
+               handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
                handles[1] = le32_to_cpu(
                    ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) |
                    RD_MAILBOX_REG(ha, reg, 6));
@@ -344,7 +319,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                break;
        }
 
-       mb[0] = LSW(mbx);
        switch (mb[0]) {
        case MBA_SCSI_COMPLETION:       /* Fast Post */
                if (!ha->flags.online)
@@ -369,11 +343,23 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
                    mb[1], mb[2], mb[3]);
 
-               if (IS_QLA2100(ha) || IS_QLA2200(ha))
-                       qla2100_fw_dump(ha, 1);
-               else
-                       qla2300_fw_dump(ha, 1);
-               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+               ha->isp_ops.fw_dump(ha, 1);
+
+               if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+                       if (mb[1] == 0 && mb[2] == 0) {
+                               qla_printk(KERN_ERR, ha,
+                                   "Unrecoverable Hardware Error: adapter "
+                                   "marked OFFLINE!\n");
+                               ha->flags.online = 0;
+                       } else
+                               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+               } else if (mb[1] == 0) {
+                       qla_printk(KERN_INFO, ha,
+                           "Unrecoverable Hardware Error: adapter marked "
+                           "OFFLINE!\n");
+                       ha->flags.online = 0;
+               } else
+                       set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                break;
 
        case MBA_REQ_TRANSFER_ERR:      /* Request Transfer Error */
@@ -398,8 +384,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                break;
 
        case MBA_LIP_OCCURRED:          /* Loop Initialization Procedure */
-               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
-
                DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no,
                    mb[1]));
                qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]);
@@ -407,27 +391,20 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
                        atomic_set(&ha->loop_state, LOOP_DOWN);
                        atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
-                       qla2x00_mark_all_devices_lost(ha);
+                       qla2x00_mark_all_devices_lost(ha, 1);
                }
 
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
 
                ha->flags.management_server_logged_in = 0;
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LIP_OCCURRED, NULL);
-
-               ha->total_lip_cnt++;
                break;
 
        case MBA_LOOP_UP:               /* Loop Up Event */
-               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
-
-               ha->link_data_rate = 0;
                if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
                        link_speed = link_speeds[0];
+                       ha->link_data_rate = PORT_SPEED_1GB;
                } else {
-                       link_speed = link_speeds[3];
+                       link_speed = link_speeds[LS_UNKNOWN];
                        if (mb[1] < 5)
                                link_speed = link_speeds[mb[1]];
                        ha->link_data_rate = mb[1];
@@ -439,33 +416,27 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                    link_speed);
 
                ha->flags.management_server_logged_in = 0;
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LOOP_UP, NULL);
                break;
 
        case MBA_LOOP_DOWN:             /* Loop Down Event */
-               DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN.\n",
-                   ha->host_no));
-               qla_printk(KERN_INFO, ha, "LOOP DOWN detected.\n");
+               DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n",
+                   ha->host_no, mb[1]));
+               qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]);
 
                if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
                        atomic_set(&ha->loop_state, LOOP_DOWN);
                        atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
                        ha->device_flags |= DFLG_NO_CABLE;
-                       qla2x00_mark_all_devices_lost(ha);
+                       qla2x00_mark_all_devices_lost(ha, 1);
                }
 
                ha->flags.management_server_logged_in = 0;
-               ha->link_data_rate = 0;
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL);
+               ha->link_data_rate = PORT_SPEED_UNKNOWN;
+               if (ql2xfdmienable)
+                       set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
                break;
 
        case MBA_LIP_RESET:             /* LIP reset occurred */
-               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
-
                DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n",
                    ha->host_no, mb[1]));
                qla_printk(KERN_INFO, ha,
@@ -474,18 +445,13 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
                        atomic_set(&ha->loop_state, LOOP_DOWN);
                        atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
-                       qla2x00_mark_all_devices_lost(ha);
+                       qla2x00_mark_all_devices_lost(ha, 1);
                }
 
                set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
 
                ha->operating_mode = LOOP;
                ha->flags.management_server_logged_in = 0;
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_LIP_RESET, NULL);
-
-               ha->total_lip_cnt++;
                break;
 
        case MBA_POINT_TO_POINT:        /* Point-to-Point */
@@ -504,21 +470,21 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                        if (!atomic_read(&ha->loop_down_timer))
                                atomic_set(&ha->loop_down_timer,
                                    LOOP_DOWN_TIME);
-                       qla2x00_mark_all_devices_lost(ha);
+                       qla2x00_mark_all_devices_lost(ha, 1);
                }
 
                if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {
                        set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
                }
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+
+               ha->flags.gpsc_supported = 1;
                break;
 
        case MBA_CHG_IN_CONNECTION:     /* Change in connection mode */
                if (IS_QLA2100(ha))
                        break;
 
-               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
-
                DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection "
                    "received.\n",
                    ha->host_no));
@@ -526,11 +492,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                    "Configuration change detected: value=%x.\n", mb[1]);
 
                if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
-                       atomic_set(&ha->loop_state, LOOP_DOWN);  
+                       atomic_set(&ha->loop_state, LOOP_DOWN);
                        if (!atomic_read(&ha->loop_down_timer))
                                atomic_set(&ha->loop_down_timer,
                                    LOOP_DOWN_TIME);
-                       qla2x00_mark_all_devices_lost(ha);
+                       qla2x00_mark_all_devices_lost(ha, 1);
                }
 
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
@@ -538,85 +504,40 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                break;
 
        case MBA_PORT_UPDATE:           /* Port database update */
-               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
-               mb[2] = RD_MAILBOX_REG(ha, reg, 2);
-
-               /*
-                * If a single remote port just logged into (or logged out of)
-                * us, create a new entry in our rscn fcports list and handle
-                * the event like an RSCN.
-                */
-               if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
-                   !IS_QLA6322(ha) && ha->flags.init_done && mb[1] != 0xffff &&
-                   ((ha->operating_mode == P2P && mb[1] != 0) ||
-                   (ha->operating_mode != P2P && mb[1] !=
-                       SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) {
-                       int rval;
-                       fc_port_t *rscn_fcport;
-
-                       /* Create new fcport for login. */
-                       rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC);
-                       if (rscn_fcport) {
-                               DEBUG14(printk("scsi(%ld): Port Update -- "
-                                   "creating RSCN fcport %p for login.\n",
-                                   ha->host_no, rscn_fcport));
-
-                               rscn_fcport->loop_id = mb[1];
-                               rscn_fcport->d_id.b24 = INVALID_PORT_ID;
-                               atomic_set(&rscn_fcport->state,
-                                   FCS_DEVICE_LOST);
-                               list_add_tail(&rscn_fcport->list,
-                                   &ha->rscn_fcports);
-
-                               rval = qla2x00_handle_port_rscn(ha, 0,
-                                   rscn_fcport, 1);
-                               if (rval == QLA_SUCCESS)
-                                       break;
-                       } else {
-                               DEBUG14(printk("scsi(%ld): Port Update -- "
-                                   "-- unable to allocate RSCN fcport "
-                                   "login.\n", ha->host_no));
-                       }
-               }
-
                /*
                 * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
                 * event etc. earlier indicating loop is down) then process
                 * it.  Otherwise ignore it and Wait for RSCN to come in.
                 */
-               if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
+               atomic_set(&ha->loop_down_timer, 0);
+               if (atomic_read(&ha->loop_state) != LOOP_DOWN &&
+                   atomic_read(&ha->loop_state) != LOOP_DEAD) {
                        DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE "
-                           "ignored.\n", ha->host_no));
+                           "ignored %04x/%04x/%04x.\n", ha->host_no, mb[1],
+                           mb[2], mb[3]));
                        break;
                }
 
                DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
                    ha->host_no));
                DEBUG(printk(KERN_INFO
-                   "scsi(%ld): Port database changed %04x %04x.\n",
-                   ha->host_no, mb[1], mb[2]));
+                   "scsi(%ld): Port database changed %04x %04x %04x.\n",
+                   ha->host_no, mb[1], mb[2], mb[3]));
 
                /*
                 * Mark all devices as missing so we will login again.
                 */
                atomic_set(&ha->loop_state, LOOP_UP);
 
-               atomic_set(&ha->loop_down_timer, 0);
-               qla2x00_mark_all_devices_lost(ha);
+               qla2x00_mark_all_devices_lost(ha, 1);
 
                ha->flags.rscn_queue_overflow = 1;
 
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
                set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_PORT_UPDATE, NULL);
                break;
 
        case MBA_RSCN_UPDATE:           /* State Change Registration */
-               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
-               mb[2] = RD_MAILBOX_REG(ha, reg, 2);
-
                DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
                    ha->host_no));
                DEBUG(printk(KERN_INFO
@@ -650,9 +571,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
 
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
                set_bit(RSCN_UPDATE, &ha->dpc_flags);
-
-               /* Update AEN queue. */
-               qla2x00_enqueue_aen(ha, MBA_RSCN_UPDATE, &mb[0]);
                break;
 
        /* case MBA_RIO_RESPONSE: */
@@ -663,11 +581,85 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
                    "scsi(%ld): [R|Z]IO update completion.\n",
                    ha->host_no));
 
-               qla2x00_process_response_queue(ha);
+               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+                       qla24xx_process_response_queue(ha);
+               else
+                       qla2x00_process_response_queue(ha);
+               break;
+
+       case MBA_DISCARD_RND_FRAME:
+               DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x "
+                   "%04x.\n", ha->host_no, mb[1], mb[2], mb[3]));
+               break;
+
+       case MBA_TRACE_NOTIFICATION:
+               DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
+               ha->host_no, mb[1], mb[2]));
                break;
        }
 }
 
+static void
+qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data)
+{
+       fc_port_t *fcport = data;
+
+       if (fcport->ha->max_q_depth <= sdev->queue_depth)
+               return;
+
+       if (sdev->ordered_tags)
+               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+                   sdev->queue_depth + 1);
+       else
+               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
+                   sdev->queue_depth + 1);
+
+       fcport->last_ramp_up = jiffies;
+
+       DEBUG2(qla_printk(KERN_INFO, fcport->ha,
+           "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
+           fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun,
+           sdev->queue_depth));
+}
+
+static void
+qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data)
+{
+       fc_port_t *fcport = data;
+
+       if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1))
+               return;
+
+       DEBUG2(qla_printk(KERN_INFO, fcport->ha,
+           "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
+           fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun,
+           sdev->queue_depth));
+}
+
+static inline void
+qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp)
+{
+       fc_port_t *fcport;
+       struct scsi_device *sdev;
+
+       sdev = sp->cmd->device;
+       if (sdev->queue_depth >= ha->max_q_depth)
+               return;
+
+       fcport = sp->fcport;
+       if (time_before(jiffies,
+           fcport->last_ramp_up + ql2xqfullrampup * HZ))
+               return;
+       if (time_before(jiffies,
+           fcport->last_queue_full + ql2xqfullrampup * HZ))
+               return;
+
+       spin_unlock_irq(&ha->hardware_lock);
+       starget_for_each_device(sdev->sdev_target, fcport,
+           qla2x00_adjust_sdev_qdepth_up);
+       spin_lock_irq(&ha->hardware_lock);
+}
+
 /**
  * qla2x00_process_completed_request() - Process a Fast Post response.
  * @ha: SCSI driver HA context
@@ -692,18 +684,16 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index)
        sp = ha->outstanding_cmds[index];
        if (sp) {
                /* Free outstanding command slot. */
-               ha->outstanding_cmds[index] = 0;
+               ha->outstanding_cmds[index] = NULL;
 
-               if (ha->actthreads)
-                       ha->actthreads--;
-               sp->lun_queue->out_cnt--;
                CMD_COMPL_STATUS(sp->cmd) = 0L;
                CMD_SCSI_STATUS(sp->cmd) = 0L;
 
                /* Save ISP completion status */
                sp->cmd->result = DID_OK << 16;
-               sp->fo_retry_cnt = 0;
-               add_to_done_queue(ha, sp);
+
+               qla2x00_ramp_up_queue_depth(ha, sp);
+               qla2x00_sp_compl(ha, sp);
        } else {
                DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n",
                    ha->host_no));
@@ -721,7 +711,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index)
 void
 qla2x00_process_response_queue(struct scsi_qla_host *ha)
 {
-       device_reg_t    *reg = ha->iobase;
+       struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
        sts_entry_t     *pkt;
        uint16_t        handle_cnt;
        uint16_t        cnt;
@@ -774,25 +764,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
                case MS_IOCB_TYPE:
                        qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
                        break;
-               case MBX_IOCB_TYPE:
-                       if (!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
-                           !IS_QLA6312(ha) && !IS_QLA6322(ha)) {
-                               if (pkt->sys_define == SOURCE_ASYNC_IOCB) {
-                                       qla2x00_process_iodesc(ha,
-                                           (struct mbx_entry *)pkt);
-                               } else {
-                                       /* MBX IOCB Type Not Supported. */
-                                       DEBUG4(printk(KERN_WARNING
-                                           "scsi(%ld): Received unknown MBX "
-                                           "IOCB response pkt type=%x "
-                                           "source=%x entry status=%x.\n",
-                                           ha->host_no, pkt->entry_type,
-                                           pkt->sys_define,
-                                           pkt->entry_status));
-                               }
-                               break;
-                       }
-                       /* Fallthrough. */
                default:
                        /* Type Not Supported. */
                        DEBUG4(printk(KERN_WARNING
@@ -815,34 +786,41 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
  * @pkt: Entry pointer
  */
 static void
-qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
+qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
 {
-       int             ret;
-       unsigned        b, t, l;
        srb_t           *sp;
-       os_lun_t        *lq;
-       os_tgt_t        *tq;
        fc_port_t       *fcport;
        struct scsi_cmnd *cp;
+       sts_entry_t *sts;
+       struct sts_entry_24xx *sts24;
        uint16_t        comp_status;
        uint16_t        scsi_status;
        uint8_t         lscsi_status;
-       uint32_t        resid;
-       uint8_t         sense_sz = 0;
-       uint16_t        rsp_info_len;
+       int32_t         resid;
+       uint32_t        sense_len, rsp_info_len, resid_len, fw_resid_len;
+       uint8_t         *rsp_info, *sense_data;
+
+       sts = (sts_entry_t *) pkt;
+       sts24 = (struct sts_entry_24xx *) pkt;
+       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+               comp_status = le16_to_cpu(sts24->comp_status);
+               scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
+       } else {
+               comp_status = le16_to_cpu(sts->comp_status);
+               scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
+       }
 
        /* Fast path completion. */
-       if (le16_to_cpu(pkt->comp_status) == CS_COMPLETE &&
-           (le16_to_cpu(pkt->scsi_status) & SS_MASK) == 0) {
-               qla2x00_process_completed_request(ha, pkt->handle);
+       if (comp_status == CS_COMPLETE && scsi_status == 0) {
+               qla2x00_process_completed_request(ha, sts->handle);
 
                return;
        }
 
        /* Validate handle. */
-       if (pkt->handle < MAX_OUTSTANDING_COMMANDS) {
-               sp = ha->outstanding_cmds[pkt->handle];
-               ha->outstanding_cmds[pkt->handle] = 0;
+       if (sts->handle < MAX_OUTSTANDING_COMMANDS) {
+               sp = ha->outstanding_cmds[sts->handle];
+               ha->outstanding_cmds[sts->handle] = NULL;
        } else
                sp = NULL;
 
@@ -852,89 +830,59 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n");
 
                set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-               if (ha->dpc_wait && !ha->dpc_active) 
-                       up(ha->dpc_wait);
-
+               qla2xxx_wake_dpc(ha);
                return;
        }
        cp = sp->cmd;
        if (cp == NULL) {
                DEBUG2(printk("scsi(%ld): Command already returned back to OS "
-                   "pkt->handle=%d sp=%p sp->state:%d\n",
-                   ha->host_no, pkt->handle, sp, sp->state));
+                   "pkt->handle=%d sp=%p.\n", ha->host_no, sts->handle, sp));
                qla_printk(KERN_WARNING, ha,
                    "Command is NULL: already returned to OS (sp=%p)\n", sp);
 
                return;
        }
 
-       if (ha->actthreads)
-               ha->actthreads--;
-
-       if (sp->lun_queue == NULL) {
-               DEBUG2(printk("scsi(%ld): Status Entry invalid lun pointer.\n",
-                   ha->host_no));
-               qla_printk(KERN_WARNING, ha,
-                   "Status Entry invalid lun pointer.\n");
-
-               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-               if (ha->dpc_wait && !ha->dpc_active) 
-                       up(ha->dpc_wait);
-
-               return;
-       }
-
-       sp->lun_queue->out_cnt--;
-
-       comp_status = le16_to_cpu(pkt->comp_status);
-       /* Mask of reserved bits 12-15, before we examine the scsi status */
-       scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK;
-       lscsi_status = scsi_status & STATUS_MASK;
-
-       CMD_ENTRY_STATUS(cp) = pkt->entry_status;
+       lscsi_status = scsi_status & STATUS_MASK;
+       CMD_ENTRY_STATUS(cp) = sts->entry_status;
        CMD_COMPL_STATUS(cp) = comp_status;
        CMD_SCSI_STATUS(cp) = scsi_status;
 
-       /* Generate LU queue on cntrl, target, LUN */
-       b = cp->device->channel;
-       t = cp->device->id;
-       l = cp->device->lun,
-
-       tq = sp->tgt_queue;
-       lq = sp->lun_queue;
-
-       /*
-        * If loop is in transient state Report DID_BUS_BUSY
-        */
-       if ((comp_status != CS_COMPLETE || scsi_status != 0)) {
-               if (!(sp->flags & SRB_IOCTL) &&
-                   (atomic_read(&ha->loop_down_timer) ||
-                       atomic_read(&ha->loop_state) != LOOP_READY)) {
-
-                       DEBUG2(printk("scsi(%ld:%d:%d:%d): Loop Not Ready - "
-                           "pid=%lx.\n",
-                           ha->host_no, b, t, l, cp->serial_number));
-
-                       qla2x00_extend_timeout(cp, EXTEND_CMD_TIMEOUT);
-                       add_to_retry_queue(ha, sp);
-                       return;
-               }
+       fcport = sp->fcport;
+
+       sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
+       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+               sense_len = le32_to_cpu(sts24->sense_len);
+               rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
+               resid_len = le32_to_cpu(sts24->rsp_residual_count);
+               fw_resid_len = le32_to_cpu(sts24->residual_len);
+               rsp_info = sts24->data;
+               sense_data = sts24->data;
+               host_to_fcp_swap(sts24->data, sizeof(sts24->data));
+       } else {
+               sense_len = le16_to_cpu(sts->req_sense_length);
+               rsp_info_len = le16_to_cpu(sts->rsp_info_len);
+               resid_len = le32_to_cpu(sts->residual_length);
+               rsp_info = sts->rsp_info;
+               sense_data = sts->req_sense_data;
        }
 
        /* Check for any FCP transport errors. */
        if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
-               rsp_info_len = le16_to_cpu(pkt->rsp_info_len);
-               if (rsp_info_len > 3 && pkt->rsp_info[3]) {
+               /* Sense data lies beyond any FCP RESPONSE data. */
+               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+                       sense_data += rsp_info_len;
+               if (rsp_info_len > 3 && rsp_info[3]) {
                        DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol "
                            "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..."
-                           "retrying command\n", ha->host_no, b, t, l,
-                           rsp_info_len, pkt->rsp_info[0], pkt->rsp_info[1],
-                           pkt->rsp_info[2], pkt->rsp_info[3],
-                           pkt->rsp_info[4], pkt->rsp_info[5],
-                           pkt->rsp_info[6], pkt->rsp_info[7]));
+                           "retrying command\n", ha->host_no,
+                           cp->device->channel, cp->device->id,
+                           cp->device->lun, rsp_info_len, rsp_info[0],
+                           rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4],
+                           rsp_info[5], rsp_info[6], rsp_info[7]));
 
                        cp->result = DID_BUS_BUSY << 16;
-                       add_to_done_queue(ha, sp);
+                       qla2x00_sp_compl(ha, sp);
                        return;
                }
        }
@@ -944,84 +892,107 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
         */
        switch (comp_status) {
        case CS_COMPLETE:
+       case CS_QUEUE_FULL:
                if (scsi_status == 0) {
                        cp->result = DID_OK << 16;
                        break;
                }
-               if (lscsi_status == SS_BUSY_CONDITION) {
-                       cp->result = DID_BUS_BUSY << 16 | lscsi_status;
-                       break;
-               }
+               if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
+                       resid = resid_len;
+                       cp->resid = resid;
+                       CMD_RESID_LEN(cp) = resid;
+
+                       if (!lscsi_status &&
+                           ((unsigned)(cp->request_bufflen - resid) <
+                            cp->underflow)) {
+                               qla_printk(KERN_INFO, ha,
+                                   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
+                                   "detected (%x of %x bytes)...returning "
+                                   "error status.\n", ha->host_no,
+                                   cp->device->channel, cp->device->id,
+                                   cp->device->lun, resid,
+                                   cp->request_bufflen);
 
+                               cp->result = DID_ERROR << 16;
+                               break;
+                       }
+               }
                cp->result = DID_OK << 16 | lscsi_status;
 
+               if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
+                       DEBUG2(printk(KERN_INFO
+                           "scsi(%ld): QUEUE FULL status detected "
+                           "0x%x-0x%x.\n", ha->host_no, comp_status,
+                           scsi_status));
+
+                       /* Adjust queue depth for all luns on the port. */
+                       fcport->last_queue_full = jiffies;
+                       spin_unlock_irq(&ha->hardware_lock);
+                       starget_for_each_device(cp->device->sdev_target,
+                           fcport, qla2x00_adjust_sdev_qdepth_down);
+                       spin_lock_irq(&ha->hardware_lock);
+                       break;
+               }
                if (lscsi_status != SS_CHECK_CONDITION)
                        break;
 
-               /*
-                * Copy Sense Data into sense buffer
-                */
+               /* Copy Sense Data into sense buffer. */
                memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer));
 
                if (!(scsi_status & SS_SENSE_LEN_VALID))
                        break;
 
-               if (le16_to_cpu(pkt->req_sense_length) <
-                   sizeof(cp->sense_buffer))
-                       sense_sz = le16_to_cpu(pkt->req_sense_length);
-               else
-                       sense_sz = sizeof(cp->sense_buffer) - 1;
+               if (sense_len >= sizeof(cp->sense_buffer))
+                       sense_len = sizeof(cp->sense_buffer);
 
-               CMD_ACTUAL_SNSLEN(cp) = sense_sz;
-               sp->request_sense_length = sense_sz;
+               CMD_ACTUAL_SNSLEN(cp) = sense_len;
+               sp->request_sense_length = sense_len;
                sp->request_sense_ptr = cp->sense_buffer;
 
                if (sp->request_sense_length > 32)
-                       sense_sz = 32;
+                       sense_len = 32;
 
-               memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz);
+               memcpy(cp->sense_buffer, sense_data, sense_len);
 
-               sp->request_sense_ptr += sense_sz;
-               sp->request_sense_length -= sense_sz;
+               sp->request_sense_ptr += sense_len;
+               sp->request_sense_length -= sense_len;
                if (sp->request_sense_length != 0)
                        ha->status_srb = sp;
 
-               if (!(sp->flags & SRB_IOCTL) &&
-                   qla2x00_check_sense(cp, lq) == QLA_SUCCESS) {
-                       /* Throw away status_cont if any */
-                       ha->status_srb = NULL;
-                       add_to_scsi_retry_queue(ha, sp);
-                       return;
-               }
-
                DEBUG5(printk("%s(): Check condition Sense data, "
-                   "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n",
-                   __func__, ha->host_no, b, t, l, cp,
-                   cp->serial_number));
-               if (sense_sz)
+                   "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", __func__,
+                   ha->host_no, cp->device->channel, cp->device->id,
+                   cp->device->lun, cp, cp->serial_number));
+               if (sense_len)
                        DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
                            CMD_ACTUAL_SNSLEN(cp)));
                break;
 
        case CS_DATA_UNDERRUN:
-               DEBUG2(printk(KERN_INFO
-                   "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n",
-                   ha->host_no, t, l, comp_status, scsi_status));
+               resid = resid_len;
+               /* Use F/W calculated residual length. */
+               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+                       resid = fw_resid_len;
+
+               if (scsi_status & SS_RESIDUAL_UNDER) {
+                       cp->resid = resid;
+                       CMD_RESID_LEN(cp) = resid;
+               } else {
+                       DEBUG2(printk(KERN_INFO
+                           "scsi(%ld:%d:%d) UNDERRUN status detected "
+                           "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x "
+                           "os_underflow=0x%x\n", ha->host_no,
+                           cp->device->id, cp->device->lun, comp_status,
+                           scsi_status, resid_len, resid, cp->cmnd[0],
+                           cp->underflow));
 
-               resid = le32_to_cpu(pkt->residual_length);
-               CMD_RESID_LEN(cp) = resid;
+               }
 
                /*
-                * Check to see if SCSI Status is non zero. If so report SCSI 
+                * Check to see if SCSI Status is non zero. If so report SCSI
                 * Status.
                 */
                if (lscsi_status != 0) {
-                       if (lscsi_status == SS_BUSY_CONDITION) {
-                               cp->result = DID_BUS_BUSY << 16 |
-                                   lscsi_status;
-                               break;
-                       }
-
                        cp->result = DID_OK << 16 | lscsi_status;
 
                        if (lscsi_status != SS_CHECK_CONDITION)
@@ -1033,37 +1004,30 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                        if (!(scsi_status & SS_SENSE_LEN_VALID))
                                break;
 
-                       if (le16_to_cpu(pkt->req_sense_length) <
-                           sizeof(cp->sense_buffer))
-                               sense_sz = le16_to_cpu(pkt->req_sense_length);
-                       else
-                               sense_sz = sizeof(cp->sense_buffer) - 1;
+                       if (sense_len >= sizeof(cp->sense_buffer))
+                               sense_len = sizeof(cp->sense_buffer);
 
-                       CMD_ACTUAL_SNSLEN(cp) = sense_sz;
-                       sp->request_sense_length = sense_sz;
+                       CMD_ACTUAL_SNSLEN(cp) = sense_len;
+                       sp->request_sense_length = sense_len;
                        sp->request_sense_ptr = cp->sense_buffer;
 
-                       if (sp->request_sense_length > 32) 
-                               sense_sz = 32;
+                       if (sp->request_sense_length > 32)
+                               sense_len = 32;
 
-                       memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz);
+                       memcpy(cp->sense_buffer, sense_data, sense_len);
 
-                       sp->request_sense_ptr += sense_sz;
-                       sp->request_sense_length -= sense_sz;
+                       sp->request_sense_ptr += sense_len;
+                       sp->request_sense_length -= sense_len;
                        if (sp->request_sense_length != 0)
                                ha->status_srb = sp;
 
-                       if (!(sp->flags & SRB_IOCTL) &&
-                           (qla2x00_check_sense(cp, lq) == QLA_SUCCESS)) {
-                               ha->status_srb = NULL;
-                               add_to_scsi_retry_queue(ha, sp);
-                               return;
-                       }
                        DEBUG5(printk("%s(): Check condition Sense data, "
                            "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n",
-                           __func__, ha->host_no, b, t, l, cp,
+                           __func__, ha->host_no, cp->device->channel,
+                           cp->device->id, cp->device->lun, cp,
                            cp->serial_number));
-                       if (sense_sz)
+
+                       if (sense_len)
                                DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
                                    CMD_ACTUAL_SNSLEN(cp)));
                } else {
@@ -1075,24 +1039,24 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                        if (!(scsi_status & SS_RESIDUAL_UNDER)) {
                                DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped "
                                    "frame(s) detected (%x of %x bytes)..."
-                                   "retrying command.\n",
-                                   ha->host_no, b, t, l, resid,
+                                   "retrying command.\n", ha->host_no,
+                                   cp->device->channel, cp->device->id,
+                                   cp->device->lun, resid,
                                    cp->request_bufflen));
 
                                cp->result = DID_BUS_BUSY << 16;
-                               ha->dropped_frame_error_cnt++;
                                break;
                        }
 
                        /* Handle mid-layer underflow */
-                       cp->resid = resid;
                        if ((unsigned)(cp->request_bufflen - resid) <
                            cp->underflow) {
                                qla_printk(KERN_INFO, ha,
                                    "scsi(%ld:%d:%d:%d): Mid-layer underflow "
                                    "detected (%x of %x bytes)...returning "
-                                   "error status.\n",
-                                   ha->host_no, b, t, l, resid,
+                                   "error status.\n", ha->host_no,
+                                   cp->device->channel, cp->device->id,
+                                   cp->device->lun, resid,
                                    cp->request_bufflen);
 
                                cp->result = DID_ERROR << 16;
@@ -1107,7 +1071,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
        case CS_DATA_OVERRUN:
                DEBUG2(printk(KERN_INFO
                    "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n",
-                   ha->host_no, t, l, comp_status, scsi_status));
+                   ha->host_no, cp->device->id, cp->device->lun, comp_status,
+                   scsi_status));
                DEBUG2(printk(KERN_INFO
                    "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
                    cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3],
@@ -1115,8 +1080,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                DEBUG2(printk(KERN_INFO
                    "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR "
                    "status!\n",
-                   cp->serial_number, cp->request_bufflen,
-                   le32_to_cpu(pkt->residual_length)));
+                   cp->serial_number, cp->request_bufflen, resid_len));
 
                cp->result = DID_ERROR << 16;
                break;
@@ -1131,30 +1095,16 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                 * Target with DID_NO_CONNECT ELSE Queue the IOs in the
                 * retry_queue.
                 */
-               fcport = sp->fclun->fcport;
                DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down "
                    "pid=%ld, compl status=0x%x, port state=0x%x\n",
-                   ha->host_no, t, l, cp->serial_number, comp_status,
+                   ha->host_no, cp->device->id, cp->device->lun,
+                   cp->serial_number, comp_status,
                    atomic_read(&fcport->state)));
 
-               if ((sp->flags & SRB_IOCTL) ||
-                   atomic_read(&fcport->state) == FCS_DEVICE_DEAD) {
-                       cp->result = DID_NO_CONNECT << 16;
-                       if (atomic_read(&ha->loop_state) == LOOP_DOWN) 
-                               sp->err_id = SRB_ERR_LOOP;
-                       else
-                               sp->err_id = SRB_ERR_PORT;
-                       add_to_done_queue(ha, sp);
-               } else {
-                       qla2x00_extend_timeout(cp, EXTEND_CMD_TIMEOUT);
-                       add_to_retry_queue(ha, sp);
-               }
-
+               cp->result = DID_BUS_BUSY << 16;
                if (atomic_read(&fcport->state) == FCS_ONLINE) {
-                       qla2x00_mark_device_lost(ha, fcport, 1);
+                       qla2x00_mark_device_lost(ha, fcport, 1, 1);
                }
-
-               return;
                break;
 
        case CS_RESET:
@@ -1162,17 +1112,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                    "scsi(%ld): RESET status detected 0x%x-0x%x.\n",
                    ha->host_no, comp_status, scsi_status));
 
-               if (sp->flags & SRB_IOCTL) {
-                       cp->result = DID_RESET << 16;
-               } else {
-                       qla2x00_extend_timeout(cp, EXTEND_CMD_TIMEOUT);
-                       add_to_retry_queue(ha, sp);
-                       return;
-               }
+               cp->result = DID_RESET << 16;
                break;
 
        case CS_ABORTED:
-               /* 
+               /*
                 * hv2.19.12 - DID_ABORT does not retry the request if we
                 * aborted this request then abort otherwise it must be a
                 * reset.
@@ -1185,45 +1129,30 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                break;
 
        case CS_TIMEOUT:
-               DEBUG2(printk(KERN_INFO
-                   "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x.\n",
-                   ha->host_no, b, t, l, comp_status, scsi_status));
-
                cp->result = DID_BUS_BUSY << 16;
 
-               fcport = lq->fclun->fcport;
-
-               /* Check to see if logout occurred */
-               if ((le16_to_cpu(pkt->status_flags) & SF_LOGOUT_SENT)) {
-                       qla2x00_mark_device_lost(ha, fcport, 1);
+               if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+                       DEBUG2(printk(KERN_INFO
+                           "scsi(%ld:%d:%d:%d): TIMEOUT status detected "
+                           "0x%x-0x%x\n", ha->host_no, cp->device->channel,
+                           cp->device->id, cp->device->lun, comp_status,
+                           scsi_status));
+                       break;
                }
-               break;
-
-       case CS_QUEUE_FULL:
                DEBUG2(printk(KERN_INFO
-                   "scsi(%ld): QUEUE FULL status detected 0x%x-0x%x.\n",
-                   ha->host_no, comp_status, scsi_status));
-
-               /* SCSI Mid-Layer handles device queue full */
-
-               cp->result = DID_OK << 16 | lscsi_status; 
-
-               /* TODO: ??? */
-               /* Adjust queue depth */
-               ret = scsi_track_queue_full(cp->device,
-                   sp->lun_queue->out_cnt - 1);
-               if (ret) {
-                       qla_printk(KERN_INFO, ha,
-                           "scsi(%ld:%d:%d:%d): Queue depth adjusted to %d.\n",
-                           ha->host_no, cp->device->channel, cp->device->id,
-                           cp->device->lun, ret);
-               }
+                   "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x "
+                   "sflags=%x.\n", ha->host_no, cp->device->channel,
+                   cp->device->id, cp->device->lun, comp_status, scsi_status,
+                   le16_to_cpu(sts->status_flags)));
+
+               /* Check to see if logout occurred. */
+               if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
+                       qla2x00_mark_device_lost(ha, fcport, 1, 1);
                break;
 
        default:
                DEBUG3(printk("scsi(%ld): Error detected (unknown status) "
-                   "0x%x-0x%x.\n",
-                   ha->host_no, comp_status, scsi_status));
+                   "0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status));
                qla_printk(KERN_INFO, ha,
                    "Unknown status detected 0x%x-0x%x.\n",
                    comp_status, scsi_status);
@@ -1234,7 +1163,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
 
        /* Place command on done queue. */
        if (ha->status_srb == NULL)
-               add_to_done_queue(ha, sp);
+               qla2x00_sp_compl(ha, sp);
 }
 
 /**
@@ -1255,10 +1184,10 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
                cp = sp->cmd;
                if (cp == NULL) {
                        DEBUG2(printk("%s(): Cmd already returned back to OS "
-                           "sp=%p sp->state:%d\n", __func__, sp, sp->state));
+                           "sp=%p.\n", __func__, sp));
                        qla_printk(KERN_INFO, ha,
                            "cmd is NULL: already returned to OS (sp=%p)\n",
-                           sp); 
+                           sp);
 
                        ha->status_srb = NULL;
                        return;
@@ -1271,6 +1200,8 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
                }
 
                /* Move sense data. */
+               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+                       host_to_fcp_swap(pkt->data, sizeof(pkt->data));
                memcpy(sp->request_sense_ptr, pkt->data, sense_sz);
                DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz));
 
@@ -1279,8 +1210,8 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
 
                /* Place command on done queue. */
                if (sp->request_sense_length == 0) {
-                       add_to_done_queue(ha, sp);
                        ha->status_srb = NULL;
+                       qla2x00_sp_compl(ha, sp);
                }
        }
 }
@@ -1291,7 +1222,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
  * @pkt: Entry pointer
  */
 static void
-qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) 
+qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
 {
        srb_t *sp;
 
@@ -1301,7 +1232,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
        else if (pkt->entry_status & RF_INV_E_COUNT)
                qla_printk(KERN_ERR, ha, "%s: Invalid Entry Count\n", __func__);
        else if (pkt->entry_status & RF_INV_E_PARAM)
-               qla_printk(KERN_ERR, ha, 
+               qla_printk(KERN_ERR, ha,
                    "%s: Invalid Entry Parameter\n", __func__);
        else if (pkt->entry_status & RF_INV_E_TYPE)
                qla_printk(KERN_ERR, ha, "%s: Invalid Entry Type\n", __func__);
@@ -1319,10 +1250,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
 
        if (sp) {
                /* Free outstanding command slot. */
-               ha->outstanding_cmds[pkt->handle] = 0;
-               if (ha->actthreads)
-                       ha->actthreads--;
-               sp->lun_queue->out_cnt--;
+               ha->outstanding_cmds[pkt->handle] = NULL;
 
                /* Bad payload or header */
                if (pkt->entry_status &
@@ -1334,19 +1262,17 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
                } else {
                        sp->cmd->result = DID_ERROR << 16;
                }
-               /* Place command on done queue. */
-               add_to_done_queue(ha, sp);
+               qla2x00_sp_compl(ha, sp);
 
-       } else if (pkt->entry_type == COMMAND_A64_TYPE ||
-           pkt->entry_type == COMMAND_TYPE) {
+       } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type ==
+           COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) {
                DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n",
                    ha->host_no));
                qla_printk(KERN_WARNING, ha,
                    "Error entry - invalid handle\n");
 
                set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-               if (ha->dpc_wait && !ha->dpc_active) 
-                       up(ha->dpc_wait);
+               qla2xxx_wake_dpc(ha);
        }
 }
 
@@ -1356,7 +1282,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
  * @index: Response queue out pointer
  */
 static void
-qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt) 
+qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt)
 {
        srb_t          *sp;
 
@@ -1382,64 +1308,231 @@ qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt)
        CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
 
        /* Free outstanding command slot. */
-       ha->outstanding_cmds[pkt->handle1] = 0;
+       ha->outstanding_cmds[pkt->handle1] = NULL;
+
+       qla2x00_sp_compl(ha, sp);
+}
+
+
+/**
+ * qla24xx_mbx_completion() - Process mailbox command completions.
+ * @ha: SCSI driver HA context
+ * @mb0: Mailbox0 register
+ */
+static void
+qla24xx_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
+{
+       uint16_t        cnt;
+       uint16_t __iomem *wptr;
+       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+       /* Load return mailbox registers. */
+       ha->flags.mbox_int = 1;
+       ha->mailbox_out[0] = mb0;
+       wptr = (uint16_t __iomem *)&reg->mailbox1;
+
+       for (cnt = 1; cnt < ha->mbx_count; cnt++) {
+               ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
+               wptr++;
+       }
+
+       if (ha->mcp) {
+               DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
+                   __func__, ha->host_no, ha->mcp->mb[0]));
+       } else {
+               DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
+                   __func__, ha->host_no));
+       }
+}
+
+/**
+ * qla24xx_process_response_queue() - Process response queue entries.
+ * @ha: SCSI driver HA context
+ */
+void
+qla24xx_process_response_queue(struct scsi_qla_host *ha)
+{
+       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+       struct sts_entry_24xx *pkt;
+
+       if (!ha->flags.online)
+               return;
+
+       while (ha->response_ring_ptr->signature != RESPONSE_PROCESSED) {
+               pkt = (struct sts_entry_24xx *)ha->response_ring_ptr;
+
+               ha->rsp_ring_index++;
+               if (ha->rsp_ring_index == ha->response_q_length) {
+                       ha->rsp_ring_index = 0;
+                       ha->response_ring_ptr = ha->response_ring;
+               } else {
+                       ha->response_ring_ptr++;
+               }
+
+               if (pkt->entry_status != 0) {
+                       DEBUG3(printk(KERN_INFO
+                           "scsi(%ld): Process error entry.\n", ha->host_no));
+
+                       qla2x00_error_entry(ha, (sts_entry_t *) pkt);
+                       ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
+                       wmb();
+                       continue;
+               }
+
+               switch (pkt->entry_type) {
+               case STATUS_TYPE:
+                       qla2x00_status_entry(ha, pkt);
+                       break;
+               case STATUS_CONT_TYPE:
+                       qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
+                       break;
+               case MS_IOCB_TYPE:
+                       qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
+                       break;
+               default:
+                       /* Type Not Supported. */
+                       DEBUG4(printk(KERN_WARNING
+                           "scsi(%ld): Received unknown response pkt type %x "
+                           "entry status=%x.\n",
+                           ha->host_no, pkt->entry_type, pkt->entry_status));
+                       break;
+               }
+               ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
+               wmb();
+       }
 
-       add_to_done_queue(ha, sp);
+       /* Adjust ring index */
+       WRT_REG_DWORD(&reg->rsp_q_out, ha->rsp_ring_index);
 }
 
 /**
- * qla2x00_check_sense() - Perform any sense data interrogation.
- * @cp: SCSI Command
- * @lq: Lun queue
+ * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
+ * @irq:
+ * @dev_id: SCSI driver HA context
  *
- * Returns QLA_SUCCESS if the lun queue is suspended, else
- * QLA_FUNCTION_FAILED  (lun queue not suspended).
+ * Called by system whenever the host adapter generates an interrupt.
+ *
+ * Returns handled flag.
  */
-static int 
-qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *lq)
+irqreturn_t
+qla24xx_intr_handler(int irq, void *dev_id)
 {
        scsi_qla_host_t *ha;
-       srb_t           *sp;
-       fc_port_t       *fcport;
+       struct device_reg_24xx __iomem *reg;
+       int             status;
+       unsigned long   flags;
+       unsigned long   iter;
+       uint32_t        stat;
+       uint32_t        hccr;
+       uint16_t        mb[4];
 
-       ha = (scsi_qla_host_t *) cp->device->host->hostdata;
-       if ((cp->sense_buffer[0] & 0x70) != 0x70) {
-               return (QLA_FUNCTION_FAILED);
+       ha = (scsi_qla_host_t *) dev_id;
+       if (!ha) {
+               printk(KERN_INFO
+                   "%s(): NULL host pointer\n", __func__);
+               return IRQ_NONE;
        }
 
-       sp = (srb_t * )CMD_SP(cp);
-       sp->flags |= SRB_GOT_SENSE;
+       reg = &ha->iobase->isp24;
+       status = 0;
 
-       switch (cp->sense_buffer[2] & 0xf) {
-       case RECOVERED_ERROR:
-               cp->result = DID_OK << 16;
-               cp->sense_buffer[0] = 0;
-               break;
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       for (iter = 50; iter--; ) {
+               stat = RD_REG_DWORD(&reg->host_status);
+               if (stat & HSRX_RISC_PAUSED) {
+                       hccr = RD_REG_DWORD(&reg->hccr);
+
+                       qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
+                           "Dumping firmware!\n", hccr);
+                       ha->isp_ops.fw_dump(ha, 1);
+                       set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+                       break;
+               } else if ((stat & HSRX_RISC_INT) == 0)
+                       break;
 
-       case NOT_READY:
-               fcport = lq->fclun->fcport;
+               switch (stat & 0xff) {
+               case 0x1:
+               case 0x2:
+               case 0x10:
+               case 0x11:
+                       qla24xx_mbx_completion(ha, MSW(stat));
+                       status |= MBX_INTERRUPT;
 
-               /*
-                * Suspend the lun only for hard disk device type.
-                */
-               if ((fcport->flags & FCF_TAPE_PRESENT) == 0 &&
-                   lq->q_state != LUN_STATE_TIMEOUT) {
-                       /*
-                        * If target is in process of being ready then suspend
-                        * lun for 6 secs and retry all the commands.
-                        */
-                       if (cp->sense_buffer[12] == 0x4 &&
-                           cp->sense_buffer[13] == 0x1) {
+                       break;
+               case 0x12:
+                       mb[0] = MSW(stat);
+                       mb[1] = RD_REG_WORD(&reg->mailbox1);
+                       mb[2] = RD_REG_WORD(&reg->mailbox2);
+                       mb[3] = RD_REG_WORD(&reg->mailbox3);
+                       qla2x00_async_event(ha, mb);
+                       break;
+               case 0x13:
+                       qla24xx_process_response_queue(ha);
+                       break;
+               default:
+                       DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
+                           "(%d).\n",
+                           ha->host_no, stat & 0xff));
+                       break;
+               }
+               WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+               RD_REG_DWORD_RELAXED(&reg->hccr);
+       }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-                               /* Suspend the lun for 6 secs */
-                               qla2x00_suspend_lun(ha, lq, 6,
-                                   ql2xsuspendcount);
+       if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+           (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+               spin_lock_irqsave(&ha->mbx_reg_lock, flags);
 
-                               return (QLA_SUCCESS);
-                       }
-               }
-               break;
+               set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+               up(&ha->mbx_intr_sem);
+
+               spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
        }
 
-       return (QLA_FUNCTION_FAILED);
+       return IRQ_HANDLED;
 }
+
+/**
+ * qla24xx_ms_entry() - Process a Management Server entry.
+ * @ha: SCSI driver HA context
+ * @index: Response queue out pointer
+ */
+static void
+qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
+{
+       srb_t          *sp;
+
+       DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
+           __func__, ha->host_no, pkt, pkt->handle));
+
+       DEBUG9(printk("%s: ct pkt dump:\n", __func__));
+       DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx)));
+
+       /* Validate handle. */
+       if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+               sp = ha->outstanding_cmds[pkt->handle];
+       else
+               sp = NULL;
+
+       if (sp == NULL) {
+               DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
+                   ha->host_no));
+               DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n",
+                   ha->host_no));
+               qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n",
+                   pkt->handle);
+
+               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+               return;
+       }
+
+       CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status);
+       CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
+
+       /* Free outstanding command slot. */
+       ha->outstanding_cmds[pkt->handle] = NULL;
+
+       qla2x00_sp_compl(ha, sp);
+}
+