diff options
author | Lalit Chandivade <lalit.chandivade@qlogic.com> | 2009-03-24 12:08:07 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-03 10:22:49 -0400 |
commit | 2533cf671da0603129c8af9c31c735e1d2654e20 (patch) | |
tree | 3ef7f6c0b4266823c07bc0687ac9009e1cc281c0 /drivers/scsi | |
parent | 1d2874de809a14e6780246b99a18bbc0fc0a8f2a (diff) |
[SCSI] qla2xxx: Correct ISP abort semantics for NVRAM, VPD, and flash update.
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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 21 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 5 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 28 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 2 |
6 files changed, 57 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 41ce1c6e56b3..117517dcbe44 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -137,12 +137,21 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, | |||
137 | *iter = chksum; | 137 | *iter = chksum; |
138 | } | 138 | } |
139 | 139 | ||
140 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | ||
141 | qla_printk(KERN_WARNING, ha, | ||
142 | "HBA not online, failing NVRAM update.\n"); | ||
143 | return -EAGAIN; | ||
144 | } | ||
145 | |||
140 | /* Write NVRAM. */ | 146 | /* Write NVRAM. */ |
141 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count); | 147 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count); |
142 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base, | 148 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base, |
143 | count); | 149 | count); |
144 | 150 | ||
151 | /* NVRAM settings take effect immediately. */ | ||
145 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 152 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
153 | qla2xxx_wake_dpc(vha); | ||
154 | qla2x00_wait_for_chip_reset(vha); | ||
146 | 155 | ||
147 | return (count); | 156 | return (count); |
148 | } | 157 | } |
@@ -330,6 +339,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
330 | if (ha->optrom_state != QLA_SWRITING) | 339 | if (ha->optrom_state != QLA_SWRITING) |
331 | break; | 340 | break; |
332 | 341 | ||
342 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | ||
343 | qla_printk(KERN_WARNING, ha, | ||
344 | "HBA not online, failing flash update.\n"); | ||
345 | return -EAGAIN; | ||
346 | } | ||
347 | |||
333 | DEBUG2(qla_printk(KERN_INFO, ha, | 348 | DEBUG2(qla_printk(KERN_INFO, ha, |
334 | "Writing flash region -- 0x%x/0x%x.\n", | 349 | "Writing flash region -- 0x%x/0x%x.\n", |
335 | ha->optrom_region_start, ha->optrom_region_size)); | 350 | ha->optrom_region_start, ha->optrom_region_size)); |
@@ -380,6 +395,12 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, | |||
380 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) | 395 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) |
381 | return 0; | 396 | return 0; |
382 | 397 | ||
398 | if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { | ||
399 | qla_printk(KERN_WARNING, ha, | ||
400 | "HBA not online, failing VPD update.\n"); | ||
401 | return -EAGAIN; | ||
402 | } | ||
403 | |||
383 | /* Write NVRAM. */ | 404 | /* Write NVRAM. */ |
384 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count); | 405 | ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count); |
385 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count); | 406 | ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count); |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index bca572f93bcc..421c6343e1c1 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2261,6 +2261,7 @@ struct qla_hw_data { | |||
2261 | uint32_t npiv_supported :1; | 2261 | uint32_t npiv_supported :1; |
2262 | uint32_t fce_enabled :1; | 2262 | uint32_t fce_enabled :1; |
2263 | uint32_t fac_supported :1; | 2263 | uint32_t fac_supported :1; |
2264 | uint32_t chip_reset_done :1; | ||
2264 | } flags; | 2265 | } flags; |
2265 | 2266 | ||
2266 | /* This spinlock is used to protect "io transactions", you must | 2267 | /* This spinlock is used to protect "io transactions", you must |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 4d52bf1c2ada..c75e7f98c242 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -110,6 +110,7 @@ extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int); | |||
110 | extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); | 110 | extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); |
111 | 111 | ||
112 | extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); | 112 | extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); |
113 | extern int qla2x00_wait_for_chip_reset(scsi_qla_host_t *); | ||
113 | 114 | ||
114 | extern void qla2xxx_wake_dpc(struct scsi_qla_host *); | 115 | extern void qla2xxx_wake_dpc(struct scsi_qla_host *); |
115 | extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *); | 116 | extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *); |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index c37888e8747d..a2747501fdde 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -61,8 +61,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
61 | int rval; | 61 | int rval; |
62 | struct qla_hw_data *ha = vha->hw; | 62 | struct qla_hw_data *ha = vha->hw; |
63 | struct req_que *req = ha->req_q_map[0]; | 63 | struct req_que *req = ha->req_q_map[0]; |
64 | |||
64 | /* Clear adapter flags. */ | 65 | /* Clear adapter flags. */ |
65 | vha->flags.online = 0; | 66 | vha->flags.online = 0; |
67 | ha->flags.chip_reset_done = 0; | ||
66 | vha->flags.reset_active = 0; | 68 | vha->flags.reset_active = 0; |
67 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | 69 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); |
68 | atomic_set(&vha->loop_state, LOOP_DOWN); | 70 | atomic_set(&vha->loop_state, LOOP_DOWN); |
@@ -131,6 +133,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
131 | } | 133 | } |
132 | } | 134 | } |
133 | rval = qla2x00_init_rings(vha); | 135 | rval = qla2x00_init_rings(vha); |
136 | ha->flags.chip_reset_done = 1; | ||
134 | 137 | ||
135 | return (rval); | 138 | return (rval); |
136 | } | 139 | } |
@@ -3321,6 +3324,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3321 | 3324 | ||
3322 | if (vha->flags.online) { | 3325 | if (vha->flags.online) { |
3323 | vha->flags.online = 0; | 3326 | vha->flags.online = 0; |
3327 | ha->flags.chip_reset_done = 0; | ||
3324 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3328 | clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
3325 | ha->qla_stats.total_isp_aborts++; | 3329 | ha->qla_stats.total_isp_aborts++; |
3326 | 3330 | ||
@@ -3470,6 +3474,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha) | |||
3470 | 3474 | ||
3471 | if (!status && !(status = qla2x00_init_rings(vha))) { | 3475 | if (!status && !(status = qla2x00_init_rings(vha))) { |
3472 | clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); | 3476 | clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); |
3477 | ha->flags.chip_reset_done = 1; | ||
3473 | /* Initialize the queues in use */ | 3478 | /* Initialize the queues in use */ |
3474 | qla25xx_init_queues(ha); | 3479 | qla25xx_init_queues(ha); |
3475 | 3480 | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c7954612ef11..1c3d165c035b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -535,6 +535,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha) | |||
535 | return (return_status); | 535 | return (return_status); |
536 | } | 536 | } |
537 | 537 | ||
538 | int | ||
539 | qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) | ||
540 | { | ||
541 | int return_status; | ||
542 | unsigned long wait_reset; | ||
543 | struct qla_hw_data *ha = vha->hw; | ||
544 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
545 | |||
546 | wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ); | ||
547 | while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) || | ||
548 | test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) || | ||
549 | test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) || | ||
550 | ha->dpc_active) && time_before(jiffies, wait_reset)) { | ||
551 | |||
552 | msleep(1000); | ||
553 | |||
554 | if (!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) && | ||
555 | ha->flags.chip_reset_done) | ||
556 | break; | ||
557 | } | ||
558 | if (ha->flags.chip_reset_done) | ||
559 | return_status = QLA_SUCCESS; | ||
560 | else | ||
561 | return_status = QLA_FUNCTION_FAILED; | ||
562 | |||
563 | return return_status; | ||
564 | } | ||
565 | |||
538 | /* | 566 | /* |
539 | * qla2x00_wait_for_loop_ready | 567 | * qla2x00_wait_for_loop_ready |
540 | * Wait for MAX_LOOP_TIMEOUT(5 min) value for loop | 568 | * Wait for MAX_LOOP_TIMEOUT(5 min) value for loop |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index ff5aa75109fc..09f893dc572d 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -1949,7 +1949,7 @@ qla2x00_resume_hba(struct scsi_qla_host *vha) | |||
1949 | clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); | 1949 | clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); |
1950 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 1950 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
1951 | qla2xxx_wake_dpc(vha); | 1951 | qla2xxx_wake_dpc(vha); |
1952 | qla2x00_wait_for_hba_online(vha); | 1952 | qla2x00_wait_for_chip_reset(vha); |
1953 | scsi_unblock_requests(vha->host); | 1953 | scsi_unblock_requests(vha->host); |
1954 | } | 1954 | } |
1955 | 1955 | ||