Commit cbc8eb67 authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley

[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: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 40859ae5
......@@ -2223,6 +2223,7 @@ struct qla_hw_data {
uint32_t fac_supported :1;
uint32_t chip_reset_done :1;
uint32_t port0 :1;
uint32_t running_gold_fw :1;
} flags;
/* This spinlock is used to protect "io transactions", you must
......@@ -2523,6 +2524,7 @@ struct qla_hw_data {
uint32_t flt_region_vpd;
uint32_t flt_region_nvram;
uint32_t flt_region_npiv_conf;
uint32_t flt_region_gold_fw;
/* Needed for BEACON */
uint16_t beacon_blink_led;
......
......@@ -1241,6 +1241,7 @@ struct qla_flt_header {
#define FLT_REG_HW_EVENT_1 0x1f
#define FLT_REG_NPIV_CONF_0 0x29
#define FLT_REG_NPIV_CONF_1 0x2a
#define FLT_REG_GOLD_FW 0x2f
struct qla_flt_region {
uint32_t code;
......
......@@ -3806,11 +3806,11 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
}
static int
qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr)
qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
uint32_t faddr)
{
int rval = QLA_SUCCESS;
int segments, fragment;
uint32_t faddr;
uint32_t *dcode, dlen;
uint32_t risc_addr;
uint32_t risc_size;
......@@ -3819,12 +3819,11 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr)
struct req_que *req = ha->req_q_map[0];
qla_printk(KERN_INFO, ha,
"FW: Loading from flash (%x)...\n", ha->flt_region_fw);
"FW: Loading from flash (%x)...\n", faddr);
rval = QLA_SUCCESS;
segments = FA_RISC_CODE_SEGMENTS;
faddr = ha->flt_region_fw;
dcode = (uint32_t *)req->ring;
*srisc_addr = 0;
......@@ -4124,27 +4123,45 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
if (rval == QLA_SUCCESS)
return rval;
return qla24xx_load_risc_flash(vha, srisc_addr);
return qla24xx_load_risc_flash(vha, srisc_addr,
vha->hw->flt_region_fw);
}
int
qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
struct qla_hw_data *ha = vha->hw;
if (ql2xfwloadbin == 2)
return qla24xx_load_risc(vha, srisc_addr);
goto try_blob_fw;
/*
* FW Load priority:
* 1) Firmware residing in flash.
* 2) Firmware via request-firmware interface (.bin file).
* 3) Golden-Firmware residing in flash -- limited operation.
*/
rval = qla24xx_load_risc_flash(vha, srisc_addr);
rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw);
if (rval == QLA_SUCCESS)
return rval;
return qla24xx_load_risc_blob(vha, srisc_addr);
try_blob_fw:
rval = qla24xx_load_risc_blob(vha, srisc_addr);
if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw)
return rval;
qla_printk(KERN_ERR, ha,
"FW: Attempting to fallback to golden firmware...\n");
rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw);
if (rval != QLA_SUCCESS)
return rval;
qla_printk(KERN_ERR, ha,
"FW: Please update operational firmware...\n");
ha->flags.running_gold_fw = 1;
return rval;
}
void
......
......@@ -1690,6 +1690,9 @@ qla2xxx_scan_start(struct Scsi_Host *shost)
{
scsi_qla_host_t *vha = shost_priv(shost);
if (vha->hw->flags.running_gold_fw)
return;
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(RSCN_UPDATE, &vha->dpc_flags);
......@@ -1962,6 +1965,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
"Can't create queues, falling back to single"
" queue mode\n");
if (ha->flags.running_gold_fw)
goto skip_dpc;
/*
* Startup the kernel thread for this host adapter
*/
......@@ -1974,6 +1980,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto probe_failed;
}
skip_dpc:
list_add_tail(&base_vha->list, &ha->vp_list);
base_vha->host->irq = ha->pdev->irq;
......
......@@ -728,6 +728,9 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
if (!ha->flags.port0)
ha->flt_region_npiv_conf = start;
break;
case FLT_REG_GOLD_FW:
ha->flt_region_gold_fw = start;
break;
}
}
goto done;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment