]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/qla2xxx/qla_isr.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[linux-2.6-omap-h63xx.git] / drivers / scsi / qla2xxx / qla_isr.c
index df69dc016a53e5525f08a054bc841bbf72d17fed..642a0c3f09c6a6a11fb9d99d884b1334d64aa651 100644 (file)
@@ -6,10 +6,10 @@
  */
 #include "qla_def.h"
 
+#include <linux/delay.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 *, uint16_t *);
 static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_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 *);
@@ -35,6 +35,7 @@ qla2100_intr_handler(int irq, void *dev_id)
        int             status;
        unsigned long   flags;
        unsigned long   iter;
+       uint16_t        hccr;
        uint16_t        mb[4];
 
        ha = (scsi_qla_host_t *) dev_id;
@@ -49,7 +50,23 @@ qla2100_intr_handler(int irq, void *dev_id)
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        for (iter = 50; iter--; ) {
-               if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
+               hccr = RD_REG_WORD(&reg->hccr);
+               if (hccr & HCCR_RISC_PAUSE) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
+                       /*
+                        * 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 ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
                        break;
 
                if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
@@ -86,12 +103,8 @@ qla2100_intr_handler(int irq, void *dev_id)
 
        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);
-
                set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-               up(&ha->mbx_intr_sem);
-
-               spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
+               complete(&ha->mbx_intr_comp);
        }
 
        return (IRQ_HANDLED);
@@ -132,13 +145,16 @@ qla2300_intr_handler(int irq, void *dev_id)
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
                if (stat & HSR_RISC_PAUSED) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
                        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.\n", hccr);
+                               qla_printk(KERN_INFO, ha, "Parity error -- "
+                                   "HCCR=%x, Dumping firmware!\n", hccr);
                        else
-                               qla_printk(KERN_INFO, ha,
-                                   "RISC paused -- HCCR=%x.\n", hccr);
+                               qla_printk(KERN_INFO, ha, "RISC paused -- "
+                                   "HCCR=%x, Dumping firmware!\n", hccr);
 
                        /*
                         * Issue a "HARD" reset in order for the RISC
@@ -147,6 +163,8 @@ qla2300_intr_handler(int irq, void *dev_id)
                         */
                        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)
@@ -197,12 +215,8 @@ qla2300_intr_handler(int irq, void *dev_id)
 
        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);
-
                set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-               up(&ha->mbx_intr_sem);
-
-               spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
+               complete(&ha->mbx_intr_comp);
        }
 
        return (IRQ_HANDLED);
@@ -250,11 +264,11 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
  * @ha: SCSI driver HA context
  * @mb: Mailbox registers (0 - 3)
  */
-static void
+void
 qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 {
 #define LS_UNKNOWN     2
-       static char     *link_speeds[5] = { "1", "2", "?", "4", "10" };
+       static char     *link_speeds[5] = { "1", "2", "?", "4", "8" };
        char            *link_speed;
        uint16_t        handle_cnt;
        uint16_t        cnt;
@@ -333,17 +347,13 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                break;
 
        case MBA_SYSTEM_ERR:            /* System Error */
-               mb[1] = RD_MAILBOX_REG(ha, reg, 1);
-               mb[2] = RD_MAILBOX_REG(ha, reg, 2);
-               mb[3] = RD_MAILBOX_REG(ha, reg, 3);
-
                qla_printk(KERN_INFO, ha,
                    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
                    mb[1], mb[2], mb[3]);
 
-               ha->isp_ops.fw_dump(ha, 1);
+               ha->isp_ops->fw_dump(ha, 1);
 
-               if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+               if (IS_FWI2_CAPABLE(ha)) {
                        if (mb[1] == 0 && mb[2] == 0) {
                                qla_printk(KERN_ERR, ha,
                                    "Unrecoverable Hardware Error: adapter "
@@ -392,6 +402,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                        qla2x00_mark_all_devices_lost(ha, 1);
                }
 
+               if (ha->parent) {
+                       atomic_set(&ha->vp_state, VP_FAILED);
+                       fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+               }
+
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
 
                ha->flags.management_server_logged_in = 0;
@@ -428,6 +443,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                        qla2x00_mark_all_devices_lost(ha, 1);
                }
 
+               if (ha->parent) {
+                       atomic_set(&ha->vp_state, VP_FAILED);
+                       fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+               }
+
                ha->flags.management_server_logged_in = 0;
                ha->link_data_rate = PORT_SPEED_UNKNOWN;
                if (ql2xfdmienable)
@@ -446,6 +466,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                        qla2x00_mark_all_devices_lost(ha, 1);
                }
 
+               if (ha->parent) {
+                       atomic_set(&ha->vp_state, VP_FAILED);
+                       fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+               }
+
                set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
 
                ha->operating_mode = LOOP;
@@ -471,10 +496,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                        qla2x00_mark_all_devices_lost(ha, 1);
                }
 
+               if (ha->parent) {
+                       atomic_set(&ha->vp_state, VP_FAILED);
+                       fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+               }
+
                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;
+               ha->flags.management_server_logged_in = 0;
                break;
 
        case MBA_CHG_IN_CONNECTION:     /* Change in connection mode */
@@ -495,6 +528,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                        qla2x00_mark_all_devices_lost(ha, 1);
                }
 
+               if (ha->parent) {
+                       atomic_set(&ha->vp_state, VP_FAILED);
+                       fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
+               }
+
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
                set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
                break;
@@ -534,11 +572,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                break;
 
        case MBA_RSCN_UPDATE:           /* State Change Registration */
+               /* Check if the Vport has issued a SCR */
+               if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
+                       break;
+               /* Only handle SCNs for our Vport index. */
+               if (ha->flags.npiv_supported && ha->vp_idx != mb[3])
+                       break;
+
                DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
                    ha->host_no));
                DEBUG(printk(KERN_INFO
-                   "scsi(%ld): RSCN database changed -- %04x %04x.\n",
-                   ha->host_no, mb[1], mb[2]));
+                   "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n",
+                   ha->host_no, mb[1], mb[2], mb[3]));
 
                rscn_entry = (mb[1] << 16) | mb[2];
                host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) |
@@ -577,7 +622,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    "scsi(%ld): [R|Z]IO update completion.\n",
                    ha->host_no));
 
-               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+               if (IS_FWI2_CAPABLE(ha))
                        qla24xx_process_response_queue(ha);
                else
                        qla2x00_process_response_queue(ha);
@@ -593,6 +638,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                ha->host_no, mb[1], mb[2]));
                break;
        }
+
+       if (!ha->parent && ha->num_vhosts)
+               qla2x00_alert_all_vps(ha, mb);
 }
 
 static void
@@ -774,6 +822,35 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
        WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), ha->rsp_ring_index);
 }
 
+static inline void
+qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
+{
+       struct scsi_cmnd *cp = sp->cmd;
+
+       if (sense_len >= SCSI_SENSE_BUFFERSIZE)
+               sense_len = SCSI_SENSE_BUFFERSIZE;
+
+       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_len = 32;
+
+       memcpy(cp->sense_buffer, sense_data, sense_len);
+
+       sp->request_sense_ptr += sense_len;
+       sp->request_sense_length -= sense_len;
+       if (sp->request_sense_length != 0)
+               sp->ha->status_srb = sp;
+
+       DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
+           "cmd=%p pid=%ld\n", __func__, sp->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)));
+}
+
 /**
  * qla2x00_status_entry() - Process a Status IOCB entry.
  * @ha: SCSI driver HA context
@@ -796,7 +873,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
 
        sts = (sts_entry_t *) pkt;
        sts24 = (struct sts_entry_24xx *) pkt;
-       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+       if (IS_FWI2_CAPABLE(ha)) {
                comp_status = le16_to_cpu(sts24->comp_status);
                scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
        } else {
@@ -845,7 +922,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
        fcport = sp->fcport;
 
        sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
-       if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+       if (IS_FWI2_CAPABLE(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);
@@ -864,7 +941,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
        /* Check for any FCP transport errors. */
        if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
                /* Sense data lies beyond any FCP RESPONSE data. */
-               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+               if (IS_FWI2_CAPABLE(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 "
@@ -893,19 +970,19 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
                }
                if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
                        resid = resid_len;
-                       cp->resid = resid;
+                       scsi_set_resid(cp, resid);
                        CMD_RESID_LEN(cp) = resid;
 
                        if (!lscsi_status &&
-                           ((unsigned)(cp->request_bufflen - resid) <
+                           ((unsigned)(scsi_bufflen(cp) - 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);
+                                          "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,
+                                          scsi_bufflen(cp));
 
                                cp->result = DID_ERROR << 16;
                                break;
@@ -928,46 +1005,27 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
                if (lscsi_status != SS_CHECK_CONDITION)
                        break;
 
-               /* Copy Sense Data into sense buffer. */
-               memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer));
-
+               memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
                if (!(scsi_status & SS_SENSE_LEN_VALID))
                        break;
 
-               if (sense_len >= sizeof(cp->sense_buffer))
-                       sense_len = sizeof(cp->sense_buffer);
-
-               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_len = 32;
-
-               memcpy(cp->sense_buffer, sense_data, sense_len);
-
-               sp->request_sense_ptr += sense_len;
-               sp->request_sense_length -= sense_len;
-               if (sp->request_sense_length != 0)
-                       ha->status_srb = sp;
-
-               DEBUG5(printk("%s(): Check condition Sense data, "
-                   "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)));
+               qla2x00_handle_sense(sp, sense_data, sense_len);
                break;
 
        case CS_DATA_UNDERRUN:
                resid = resid_len;
                /* Use F/W calculated residual length. */
-               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+               if (IS_FWI2_CAPABLE(ha)) {
+                       if (scsi_status & SS_RESIDUAL_UNDER &&
+                           resid != fw_resid_len) {
+                               scsi_status &= ~SS_RESIDUAL_UNDER;
+                               lscsi_status = 0;
+                       }
                        resid = fw_resid_len;
+               }
 
                if (scsi_status & SS_RESIDUAL_UNDER) {
-                       cp->resid = resid;
+                       scsi_set_resid(cp, resid);
                        CMD_RESID_LEN(cp) = resid;
                } else {
                        DEBUG2(printk(KERN_INFO
@@ -1006,38 +1064,30 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
                        if (lscsi_status != SS_CHECK_CONDITION)
                                break;
 
-                       /* Copy Sense Data into sense buffer */
-                       memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer));
-
+                       memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
                        if (!(scsi_status & SS_SENSE_LEN_VALID))
                                break;
 
-                       if (sense_len >= sizeof(cp->sense_buffer))
-                               sense_len = sizeof(cp->sense_buffer);
-
-                       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_len = 32;
+                       qla2x00_handle_sense(sp, sense_data, sense_len);
 
-                       memcpy(cp->sense_buffer, sense_data, sense_len);
-
-                       sp->request_sense_ptr += sense_len;
-                       sp->request_sense_length -= sense_len;
-                       if (sp->request_sense_length != 0)
-                               ha->status_srb = sp;
-
-                       DEBUG5(printk("%s(): Check condition Sense data, "
-                           "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));
+                       /*
+                        * In case of a Underrun condition, set both the lscsi
+                        * status and the completion status to appropriate
+                        * values.
+                        */
+                       if (resid &&
+                           ((unsigned)(scsi_bufflen(cp) - resid) <
+                            cp->underflow)) {
+                               DEBUG2(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,
+                                   scsi_bufflen(cp)));
 
-                       if (sense_len)
-                               DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
-                                   CMD_ACTUAL_SNSLEN(cp)));
+                               cp->result = DID_ERROR << 16 | lscsi_status;
+                       }
                } else {
                        /*
                         * If RISC reports underrun and target does not report
@@ -1046,26 +1096,26 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *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,
-                                   cp->device->channel, cp->device->id,
-                                   cp->device->lun, resid,
-                                   cp->request_bufflen));
+                                             "frame(s) detected (%x of %x bytes)..."
+                                             "retrying command.\n", ha->host_no,
+                                             cp->device->channel, cp->device->id,
+                                             cp->device->lun, resid,
+                                             scsi_bufflen(cp)));
 
                                cp->result = DID_BUS_BUSY << 16;
                                break;
                        }
 
                        /* Handle mid-layer underflow */
-                       if ((unsigned)(cp->request_bufflen - resid) <
+                       if ((unsigned)(scsi_bufflen(cp) - 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);
+                                          "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,
+                                          scsi_bufflen(cp));
 
                                cp->result = DID_ERROR << 16;
                                break;
@@ -1088,7 +1138,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *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, resid_len));
+                   cp->serial_number, scsi_bufflen(cp), resid_len));
 
                cp->result = DID_ERROR << 16;
                break;
@@ -1139,7 +1189,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
        case CS_TIMEOUT:
                cp->result = DID_BUS_BUSY << 16;
 
-               if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+               if (IS_FWI2_CAPABLE(ha)) {
                        DEBUG2(printk(KERN_INFO
                            "scsi(%ld:%d:%d:%d): TIMEOUT status detected "
                            "0x%x-0x%x\n", ha->host_no, cp->device->channel,
@@ -1208,7 +1258,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt)
                }
 
                /* Move sense data. */
-               if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+               if (IS_FWI2_CAPABLE(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));
@@ -1397,6 +1447,10 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
                case MS_IOCB_TYPE:
                        qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
                        break;
+               case VP_RPT_ID_IOCB_TYPE:
+                       qla24xx_report_id_acquisition(ha,
+                           (struct vp_rpt_id_entry_24xx *)pkt);
+                       break;
                default:
                        /* Type Not Supported. */
                        DEBUG4(printk(KERN_WARNING
@@ -1413,6 +1467,52 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
        WRT_REG_DWORD(&reg->rsp_q_out, ha->rsp_ring_index);
 }
 
+static void
+qla2xxx_check_risc_status(scsi_qla_host_t *ha)
+{
+       int rval;
+       uint32_t cnt;
+       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+       if (!IS_QLA25XX(ha))
+               return;
+
+       rval = QLA_SUCCESS;
+       WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
+       RD_REG_DWORD(&reg->iobase_addr);
+       WRT_REG_DWORD(&reg->iobase_window, 0x0001);
+       for (cnt = 10000; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
+           rval == QLA_SUCCESS; cnt--) {
+               if (cnt) {
+                       WRT_REG_DWORD(&reg->iobase_window, 0x0001);
+                       udelay(10);
+               } else
+                       rval = QLA_FUNCTION_TIMEOUT;
+       }
+       if (rval == QLA_SUCCESS)
+               goto next_test;
+
+       WRT_REG_DWORD(&reg->iobase_window, 0x0003);
+       for (cnt = 100; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
+           rval == QLA_SUCCESS; cnt--) {
+               if (cnt) {
+                       WRT_REG_DWORD(&reg->iobase_window, 0x0003);
+                       udelay(10);
+               } else
+                       rval = QLA_FUNCTION_TIMEOUT;
+       }
+       if (rval != QLA_SUCCESS)
+               goto done;
+
+next_test:
+       if (RD_REG_DWORD(&reg->iobase_c8) & BIT_3)
+               qla_printk(KERN_INFO, ha, "Additional code -- 0x55AA.\n");
+
+done:
+       WRT_REG_DWORD(&reg->iobase_window, 0x0000);
+       RD_REG_DWORD(&reg->iobase_window);
+}
+
 /**
  * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
  * @irq:
@@ -1448,12 +1548,17 @@ qla24xx_intr_handler(int irq, void *dev_id)
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
                        hccr = RD_REG_DWORD(&reg->hccr);
 
                        qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
                            "Dumping firmware!\n", hccr);
-                       qla24xx_fw_dump(ha, 1);
 
+                       qla2xxx_check_risc_status(ha);
+
+                       ha->isp_ops->fw_dump(ha, 1);
                        set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                        break;
                } else if ((stat & HSRX_RISC_INT) == 0)
@@ -1491,12 +1596,8 @@ qla24xx_intr_handler(int irq, void *dev_id)
 
        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);
-
                set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-               up(&ha->mbx_intr_sem);
-
-               spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
+               complete(&ha->mbx_intr_comp);
        }
 
        return IRQ_HANDLED;
@@ -1560,7 +1661,6 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
        qla24xx_process_response_queue(ha);
 
        WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-       RD_REG_DWORD_RELAXED(&reg->hccr);
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
@@ -1574,7 +1674,6 @@ qla24xx_msix_default(int irq, void *dev_id)
        struct device_reg_24xx __iomem *reg;
        int             status;
        unsigned long   flags;
-       unsigned long   iter;
        uint32_t        stat;
        uint32_t        hccr;
        uint16_t        mb[4];
@@ -1584,14 +1683,20 @@ qla24xx_msix_default(int irq, void *dev_id)
        status = 0;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
-       for (iter = 50; iter--; ) {
+       do {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
+                       if (pci_channel_offline(ha->pdev))
+                               break;
+
                        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);
+
+                       qla2xxx_check_risc_status(ha);
+
+                       ha->isp_ops->fw_dump(ha, 1);
                        set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                        break;
                } else if ((stat & HSRX_RISC_INT) == 0)
@@ -1623,18 +1728,13 @@ qla24xx_msix_default(int irq, void *dev_id)
                        break;
                }
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-               RD_REG_DWORD_RELAXED(&reg->hccr);
-       }
+       } while (0);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        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);
-
                set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
-               up(&ha->mbx_intr_sem);
-
-               spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
+               complete(&ha->mbx_intr_comp);
        }
 
        return IRQ_HANDLED;
@@ -1646,7 +1746,7 @@ struct qla_init_msix_entry {
        uint16_t entry;
        uint16_t index;
        const char *name;
-       irqreturn_t (*handler)(int, void *);
+       irq_handler_t handler;
 };
 
 static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
@@ -1717,11 +1817,11 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
        int ret;
 
        /* If possible, enable MSI-X. */
-       if (!IS_QLA2432(ha))
+       if (!IS_QLA2432(ha) && !IS_QLA2532(ha))
                goto skip_msix;
 
-        if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
-           !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) {
+        if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
+           !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) {
                DEBUG2(qla_printk(KERN_WARNING, ha,
                    "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
                    ha->chip_revision, ha->fw_attributes));
@@ -1729,6 +1829,18 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
                goto skip_msix;
        }
 
+       if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
+           (ha->pdev->subsystem_device == 0x7040 ||
+               ha->pdev->subsystem_device == 0x7041 ||
+               ha->pdev->subsystem_device == 0x1705)) {
+               DEBUG2(qla_printk(KERN_WARNING, ha,
+                   "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X, 0x%X).\n",
+                   ha->pdev->subsystem_vendor,
+                   ha->pdev->subsystem_device));
+
+               goto skip_msi;
+       }
+
        ret = qla24xx_enable_msix(ha);
        if (!ret) {
                DEBUG2(qla_printk(KERN_INFO, ha,
@@ -1739,7 +1851,18 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
        qla_printk(KERN_WARNING, ha,
            "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
 skip_msix:
-       ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler,
+
+       if (!IS_QLA24XX(ha) && !IS_QLA2532(ha))
+               goto skip_msi;
+
+       ret = pci_enable_msi(ha->pdev);
+       if (!ret) {
+               DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
+               ha->flags.msi_enabled = 1;
+       }
+skip_msi:
+
+       ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
            IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
        if (!ret) {
                ha->flags.inta_enabled = 1;
@@ -1759,6 +1882,8 @@ qla2x00_free_irqs(scsi_qla_host_t *ha)
 
        if (ha->flags.msix_enabled)
                qla24xx_disable_msix(ha);
-       else if (ha->flags.inta_enabled)
+       else if (ha->flags.inta_enabled) {
                free_irq(ha->host->irq, ha);
+               pci_disable_msi(ha->pdev);
+       }
 }