[SCSI] qla4xxx: Fix processing response queue during probe
authorTej Parkash <tej.parkash@qlogic.com>
Mon, 16 Dec 2013 11:49:42 +0000 (06:49 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Sat, 15 Mar 2014 17:19:14 +0000 (10:19 -0700)
Issue:
While booting with kdump kernel, driver receive IOCB interrupts
for which it is not ready which results in processing them
before init_firmware during driver probe

Fix:
Two steps solution
1. Make driver ready to process the interrupt before interupts
   handlers is registered.
2. Stop driver processing iocb interrupts if not generated as per
   firmware protocol i.e R2H bit set

Signed-off-by: Tej Parkash <tej.parkash@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla4xxx/ql4_isr.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_nx.c

index 49032f640da1ed1150b5307ce397699a9cedf474..df3fd9b4561ee85cddbbeb097231692a28e9ae70 100644 (file)
@@ -1022,7 +1022,8 @@ void qla4_82xx_interrupt_service_routine(struct scsi_qla_host *ha,
     uint32_t intr_status)
 {
        /* Process response queue interrupt. */
-       if (intr_status & HSRX_RISC_IOCB_INT)
+       if ((intr_status & HSRX_RISC_IOCB_INT) &&
+           test_bit(AF_INIT_DONE, &ha->flags))
                qla4xxx_process_response_queue(ha);
 
        /* Process mailbox/asynch event interrupt.*/
@@ -1399,6 +1400,7 @@ qla4_8xxx_msix_rsp_q(int irq, void *dev_id)
 {
        struct scsi_qla_host *ha = dev_id;
        unsigned long flags;
+       int intr_status;
        uint32_t ival = 0;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -1412,8 +1414,15 @@ qla4_8xxx_msix_rsp_q(int irq, void *dev_id)
                qla4xxx_process_response_queue(ha);
                writel(0, &ha->qla4_83xx_reg->iocb_int_mask);
        } else {
-               qla4xxx_process_response_queue(ha);
-               writel(0, &ha->qla4_82xx_reg->host_int);
+               intr_status = readl(&ha->qla4_82xx_reg->host_status);
+               if (intr_status & HSRX_RISC_IOCB_INT) {
+                       qla4xxx_process_response_queue(ha);
+                       writel(0, &ha->qla4_82xx_reg->host_int);
+               } else {
+                       ql4_printk(KERN_INFO, ha, "%s: spurious iocb interrupt...\n",
+                                  __func__);
+                       goto exit_msix_rsp_q;
+               }
        }
        ha->isr_count++;
 exit_msix_rsp_q:
index 6905bad3e15cda76d6df52521b0e1d135847a646..52c0a48ab41fe722b6a6f95043179d4a3d329814 100644 (file)
@@ -648,9 +648,6 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
                goto exit_init_fw_cb;
        }
 
-       /* Initialize request and response queues. */
-       qla4xxx_init_rings(ha);
-
        /* Fill in the request and response queue information. */
        init_fw_cb->rqq_consumer_idx = cpu_to_le16(ha->request_out);
        init_fw_cb->compq_producer_idx = cpu_to_le16(ha->response_in);
index cbc68f915cc68b34f85167472a95eaa313385ef7..bcf3e43e024adaccfd5f38600a0a86ea18d53c5d 100644 (file)
@@ -3190,6 +3190,10 @@ int qla4_8xxx_load_risc(struct scsi_qla_host *ha)
 
        retval = qla4_8xxx_device_state_handler(ha);
 
+       /* Initialize request and response queues. */
+       if (retval == QLA_SUCCESS)
+               qla4xxx_init_rings(ha);
+
        if (retval == QLA_SUCCESS && !test_bit(AF_IRQ_ATTACHED, &ha->flags))
                retval = qla4xxx_request_irqs(ha);