[SCSI] qla2xxx: Correct ISP abort semantics for NVRAM, VPD, and flash update.
authorLalit Chandivade <lalit.chandivade@qlogic.com>
Tue, 24 Mar 2009 16:08:07 +0000 (09:08 -0700)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Fri, 3 Apr 2009 14:22:49 +0000 (09:22 -0500)
Ensure that an ISP-abort has completed before performing any
update.  After the update do not wait for an ISP-abort completion,
instead just wait until the ISP is reset.  This avoids long
delays due to waiting for loop ready in qla2x00_abort_isp().

Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Additional cleanups and
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c

index 41ce1c6e56b31f569395301b36bfb4be821ce01f..117517dcbe44934a35eb165dbab182f70691a658 100644 (file)
@@ -137,12 +137,21 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
                *iter = chksum;
        }
 
+       if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+               qla_printk(KERN_WARNING, ha,
+                   "HBA not online, failing NVRAM update.\n");
+               return -EAGAIN;
+       }
+
        /* Write NVRAM. */
        ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count);
        ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base,
            count);
 
+       /* NVRAM settings take effect immediately. */
        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+       qla2xxx_wake_dpc(vha);
+       qla2x00_wait_for_chip_reset(vha);
 
        return (count);
 }
@@ -330,6 +339,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
                if (ha->optrom_state != QLA_SWRITING)
                        break;
 
+               if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+                       qla_printk(KERN_WARNING, ha,
+                           "HBA not online, failing flash update.\n");
+                       return -EAGAIN;
+               }
+
                DEBUG2(qla_printk(KERN_INFO, ha,
                    "Writing flash region -- 0x%x/0x%x.\n",
                    ha->optrom_region_start, ha->optrom_region_size));
@@ -380,6 +395,12 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
        if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
                return 0;
 
+       if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+               qla_printk(KERN_WARNING, ha,
+                   "HBA not online, failing VPD update.\n");
+               return -EAGAIN;
+       }
+
        /* Write NVRAM. */
        ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count);
        ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count);
index bca572f93bccb4d5ac5613b642a988b0ac9b8da1..421c6343e1c1b16611fc718b60db846f23461060 100644 (file)
@@ -2261,6 +2261,7 @@ struct qla_hw_data {
                uint32_t        npiv_supported          :1;
                uint32_t        fce_enabled             :1;
                uint32_t        fac_supported           :1;
+               uint32_t        chip_reset_done         :1;
        } flags;
 
        /* This spinlock is used to protect "io transactions", you must
index 4d52bf1c2ada2a57423064d06d23515fd29408c7..c75e7f98c242af30a82709cf95fe31e1292ac402 100644 (file)
@@ -110,6 +110,7 @@ extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
 extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
 
 extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
+extern int qla2x00_wait_for_chip_reset(scsi_qla_host_t *);
 
 extern void qla2xxx_wake_dpc(struct scsi_qla_host *);
 extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *);
index c37888e8747d17b5213df3ac46a427db2fac7c60..a2747501fdde20161ea8241818ecadc589fe92d3 100644 (file)
@@ -61,8 +61,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
        int     rval;
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = ha->req_q_map[0];
+
        /* Clear adapter flags. */
        vha->flags.online = 0;
+       ha->flags.chip_reset_done = 0;
        vha->flags.reset_active = 0;
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
        atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -131,6 +133,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
                }
        }
        rval = qla2x00_init_rings(vha);
+       ha->flags.chip_reset_done = 1;
 
        return (rval);
 }
@@ -3321,6 +3324,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
 
        if (vha->flags.online) {
                vha->flags.online = 0;
+               ha->flags.chip_reset_done = 0;
                clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
                ha->qla_stats.total_isp_aborts++;
 
@@ -3470,6 +3474,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
 
        if (!status && !(status = qla2x00_init_rings(vha))) {
                clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
+               ha->flags.chip_reset_done = 1;
                /* Initialize the queues in use */
                qla25xx_init_queues(ha);
 
index c7954612ef11931466883e7f1e7ecdcbea4a4994..1c3d165c035bb97bf7bf60dec23acc6be2511c8e 100644 (file)
@@ -535,6 +535,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
        return (return_status);
 }
 
+int
+qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
+{
+       int             return_status;
+       unsigned long   wait_reset;
+       struct qla_hw_data *ha = vha->hw;
+       scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+
+       wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ);
+       while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
+           test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
+           test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
+           ha->dpc_active) && time_before(jiffies, wait_reset)) {
+
+               msleep(1000);
+
+               if (!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
+                   ha->flags.chip_reset_done)
+                       break;
+       }
+       if (ha->flags.chip_reset_done)
+               return_status = QLA_SUCCESS;
+       else
+               return_status = QLA_FUNCTION_FAILED;
+
+       return return_status;
+}
+
 /*
  * qla2x00_wait_for_loop_ready
  *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
index ff5aa75109fcd03833c86bf46a50ef599d3ddc4c..09f893dc572d33f06a64913da9c15d24cc80c017 100644 (file)
@@ -1949,7 +1949,7 @@ qla2x00_resume_hba(struct scsi_qla_host *vha)
        clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
        qla2xxx_wake_dpc(vha);
-       qla2x00_wait_for_hba_online(vha);
+       qla2x00_wait_for_chip_reset(vha);
        scsi_unblock_requests(vha->host);
 }