diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2009-06-03 12:55:17 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-08 15:46:41 -0400 |
commit | cbc8eb67da11a4972834f61fe4729f4c037a17c9 (patch) | |
tree | 52880ae49bce8a8b733d0d59bd84b324eb0871ef /drivers/scsi/qla2xxx | |
parent | 40859ae5f13534624cc35a05179b4f93ecbf531a (diff) |
[SCSI] qla2xxx: Fallback to 'golden-firmware' operation on supported ISPs.
In case the onboard firmware is unable to be read or loaded for
operation, attempt to fallback to a limited-operational firmware
image stored in a different flash region. This will allow a user
to reflash and correct a board with proper operational firmware.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 33 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 3 |
5 files changed, 38 insertions, 8 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4e846ae928aa..88ddae0e2b88 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2223,6 +2223,7 @@ struct qla_hw_data { | |||
2223 | uint32_t fac_supported :1; | 2223 | uint32_t fac_supported :1; |
2224 | uint32_t chip_reset_done :1; | 2224 | uint32_t chip_reset_done :1; |
2225 | uint32_t port0 :1; | 2225 | uint32_t port0 :1; |
2226 | uint32_t running_gold_fw :1; | ||
2226 | } flags; | 2227 | } flags; |
2227 | 2228 | ||
2228 | /* This spinlock is used to protect "io transactions", you must | 2229 | /* This spinlock is used to protect "io transactions", you must |
@@ -2523,6 +2524,7 @@ struct qla_hw_data { | |||
2523 | uint32_t flt_region_vpd; | 2524 | uint32_t flt_region_vpd; |
2524 | uint32_t flt_region_nvram; | 2525 | uint32_t flt_region_nvram; |
2525 | uint32_t flt_region_npiv_conf; | 2526 | uint32_t flt_region_npiv_conf; |
2527 | uint32_t flt_region_gold_fw; | ||
2526 | 2528 | ||
2527 | /* Needed for BEACON */ | 2529 | /* Needed for BEACON */ |
2528 | uint16_t beacon_blink_led; | 2530 | uint16_t beacon_blink_led; |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 152d16c77f3e..9e56d4a4cb75 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -1241,6 +1241,7 @@ struct qla_flt_header { | |||
1241 | #define FLT_REG_HW_EVENT_1 0x1f | 1241 | #define FLT_REG_HW_EVENT_1 0x1f |
1242 | #define FLT_REG_NPIV_CONF_0 0x29 | 1242 | #define FLT_REG_NPIV_CONF_0 0x29 |
1243 | #define FLT_REG_NPIV_CONF_1 0x2a | 1243 | #define FLT_REG_NPIV_CONF_1 0x2a |
1244 | #define FLT_REG_GOLD_FW 0x2f | ||
1244 | 1245 | ||
1245 | struct qla_flt_region { | 1246 | struct qla_flt_region { |
1246 | uint32_t code; | 1247 | uint32_t code; |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a7abc1035481..34e6508bbab0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -3806,11 +3806,11 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) | |||
3806 | } | 3806 | } |
3807 | 3807 | ||
3808 | static int | 3808 | static int |
3809 | qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr) | 3809 | qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, |
3810 | uint32_t faddr) | ||
3810 | { | 3811 | { |
3811 | int rval = QLA_SUCCESS; | 3812 | int rval = QLA_SUCCESS; |
3812 | int segments, fragment; | 3813 | int segments, fragment; |
3813 | uint32_t faddr; | ||
3814 | uint32_t *dcode, dlen; | 3814 | uint32_t *dcode, dlen; |
3815 | uint32_t risc_addr; | 3815 | uint32_t risc_addr; |
3816 | uint32_t risc_size; | 3816 | uint32_t risc_size; |
@@ -3819,12 +3819,11 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr) | |||
3819 | struct req_que *req = ha->req_q_map[0]; | 3819 | struct req_que *req = ha->req_q_map[0]; |
3820 | 3820 | ||
3821 | qla_printk(KERN_INFO, ha, | 3821 | qla_printk(KERN_INFO, ha, |
3822 | "FW: Loading from flash (%x)...\n", ha->flt_region_fw); | 3822 | "FW: Loading from flash (%x)...\n", faddr); |
3823 | 3823 | ||
3824 | rval = QLA_SUCCESS; | 3824 | rval = QLA_SUCCESS; |
3825 | 3825 | ||
3826 | segments = FA_RISC_CODE_SEGMENTS; | 3826 | segments = FA_RISC_CODE_SEGMENTS; |
3827 | faddr = ha->flt_region_fw; | ||
3828 | dcode = (uint32_t *)req->ring; | 3827 | dcode = (uint32_t *)req->ring; |
3829 | *srisc_addr = 0; | 3828 | *srisc_addr = 0; |
3830 | 3829 | ||
@@ -4124,27 +4123,45 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) | |||
4124 | if (rval == QLA_SUCCESS) | 4123 | if (rval == QLA_SUCCESS) |
4125 | return rval; | 4124 | return rval; |
4126 | 4125 | ||
4127 | return qla24xx_load_risc_flash(vha, srisc_addr); | 4126 | return qla24xx_load_risc_flash(vha, srisc_addr, |
4127 | vha->hw->flt_region_fw); | ||
4128 | } | 4128 | } |
4129 | 4129 | ||
4130 | int | 4130 | int |
4131 | qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) | 4131 | qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) |
4132 | { | 4132 | { |
4133 | int rval; | 4133 | int rval; |
4134 | struct qla_hw_data *ha = vha->hw; | ||
4134 | 4135 | ||
4135 | if (ql2xfwloadbin == 2) | 4136 | if (ql2xfwloadbin == 2) |
4136 | return qla24xx_load_risc(vha, srisc_addr); | 4137 | goto try_blob_fw; |
4137 | 4138 | ||
4138 | /* | 4139 | /* |
4139 | * FW Load priority: | 4140 | * FW Load priority: |
4140 | * 1) Firmware residing in flash. | 4141 | * 1) Firmware residing in flash. |
4141 | * 2) Firmware via request-firmware interface (.bin file). | 4142 | * 2) Firmware via request-firmware interface (.bin file). |
4143 | * 3) Golden-Firmware residing in flash -- limited operation. | ||
4142 | */ | 4144 | */ |
4143 | rval = qla24xx_load_risc_flash(vha, srisc_addr); | 4145 | rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw); |
4144 | if (rval == QLA_SUCCESS) | 4146 | if (rval == QLA_SUCCESS) |
4145 | return rval; | 4147 | return rval; |
4146 | 4148 | ||
4147 | return qla24xx_load_risc_blob(vha, srisc_addr); | 4149 | try_blob_fw: |
4150 | rval = qla24xx_load_risc_blob(vha, srisc_addr); | ||
4151 | if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw) | ||
4152 | return rval; | ||
4153 | |||
4154 | qla_printk(KERN_ERR, ha, | ||
4155 | "FW: Attempting to fallback to golden firmware...\n"); | ||
4156 | rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw); | ||
4157 | if (rval != QLA_SUCCESS) | ||
4158 | return rval; | ||
4159 | |||
4160 | qla_printk(KERN_ERR, ha, | ||
4161 | "FW: Please update operational firmware...\n"); | ||
4162 | ha->flags.running_gold_fw = 1; | ||
4163 | |||
4164 | return rval; | ||
4148 | } | 4165 | } |
4149 | 4166 | ||
4150 | void | 4167 | void |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 181ed971a2ff..128b3d5c9663 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1690,6 +1690,9 @@ qla2xxx_scan_start(struct Scsi_Host *shost) | |||
1690 | { | 1690 | { |
1691 | scsi_qla_host_t *vha = shost_priv(shost); | 1691 | scsi_qla_host_t *vha = shost_priv(shost); |
1692 | 1692 | ||
1693 | if (vha->hw->flags.running_gold_fw) | ||
1694 | return; | ||
1695 | |||
1693 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | 1696 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); |
1694 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); | 1697 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); |
1695 | set_bit(RSCN_UPDATE, &vha->dpc_flags); | 1698 | set_bit(RSCN_UPDATE, &vha->dpc_flags); |
@@ -1962,6 +1965,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1962 | "Can't create queues, falling back to single" | 1965 | "Can't create queues, falling back to single" |
1963 | " queue mode\n"); | 1966 | " queue mode\n"); |
1964 | 1967 | ||
1968 | if (ha->flags.running_gold_fw) | ||
1969 | goto skip_dpc; | ||
1970 | |||
1965 | /* | 1971 | /* |
1966 | * Startup the kernel thread for this host adapter | 1972 | * Startup the kernel thread for this host adapter |
1967 | */ | 1973 | */ |
@@ -1974,6 +1980,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1974 | goto probe_failed; | 1980 | goto probe_failed; |
1975 | } | 1981 | } |
1976 | 1982 | ||
1983 | skip_dpc: | ||
1977 | list_add_tail(&base_vha->list, &ha->vp_list); | 1984 | list_add_tail(&base_vha->list, &ha->vp_list); |
1978 | base_vha->host->irq = ha->pdev->irq; | 1985 | base_vha->host->irq = ha->pdev->irq; |
1979 | 1986 | ||
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index e239203f19f7..6260505dceb5 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -728,6 +728,9 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) | |||
728 | if (!ha->flags.port0) | 728 | if (!ha->flags.port0) |
729 | ha->flt_region_npiv_conf = start; | 729 | ha->flt_region_npiv_conf = start; |
730 | break; | 730 | break; |
731 | case FLT_REG_GOLD_FW: | ||
732 | ha->flt_region_gold_fw = start; | ||
733 | break; | ||
731 | } | 734 | } |
732 | } | 735 | } |
733 | goto done; | 736 | goto done; |