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 { ...@@ -2223,6 +2223,7 @@ struct qla_hw_data {
uint32_t fac_supported :1; uint32_t fac_supported :1;
uint32_t chip_reset_done :1; uint32_t chip_reset_done :1;
uint32_t port0 :1; uint32_t port0 :1;
uint32_t running_gold_fw :1;
} flags; } flags;
/* This spinlock is used to protect "io transactions", you must /* This spinlock is used to protect "io transactions", you must
...@@ -2523,6 +2524,7 @@ struct qla_hw_data { ...@@ -2523,6 +2524,7 @@ struct qla_hw_data {
uint32_t flt_region_vpd; uint32_t flt_region_vpd;
uint32_t flt_region_nvram; uint32_t flt_region_nvram;
uint32_t flt_region_npiv_conf; uint32_t flt_region_npiv_conf;
uint32_t flt_region_gold_fw;
/* Needed for BEACON */ /* Needed for BEACON */
uint16_t beacon_blink_led; uint16_t beacon_blink_led;
......
...@@ -1241,6 +1241,7 @@ struct qla_flt_header { ...@@ -1241,6 +1241,7 @@ struct qla_flt_header {
#define FLT_REG_HW_EVENT_1 0x1f #define FLT_REG_HW_EVENT_1 0x1f
#define FLT_REG_NPIV_CONF_0 0x29 #define FLT_REG_NPIV_CONF_0 0x29
#define FLT_REG_NPIV_CONF_1 0x2a #define FLT_REG_NPIV_CONF_1 0x2a
#define FLT_REG_GOLD_FW 0x2f
struct qla_flt_region { struct qla_flt_region {
uint32_t code; uint32_t code;
......
...@@ -3806,11 +3806,11 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) ...@@ -3806,11 +3806,11 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
} }
static int 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 rval = QLA_SUCCESS;
int segments, fragment; int segments, fragment;
uint32_t faddr;
uint32_t *dcode, dlen; uint32_t *dcode, dlen;
uint32_t risc_addr; uint32_t risc_addr;
uint32_t risc_size; uint32_t risc_size;
...@@ -3819,12 +3819,11 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr) ...@@ -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]; struct req_que *req = ha->req_q_map[0];
qla_printk(KERN_INFO, ha, 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; rval = QLA_SUCCESS;
segments = FA_RISC_CODE_SEGMENTS; segments = FA_RISC_CODE_SEGMENTS;
faddr = ha->flt_region_fw;
dcode = (uint32_t *)req->ring; dcode = (uint32_t *)req->ring;
*srisc_addr = 0; *srisc_addr = 0;
...@@ -4124,27 +4123,45 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) ...@@ -4124,27 +4123,45 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
if (rval == QLA_SUCCESS) if (rval == QLA_SUCCESS)
return rval; return rval;
return qla24xx_load_risc_flash(vha, srisc_addr); return qla24xx_load_risc_flash(vha, srisc_addr,
vha->hw->flt_region_fw);
} }
int int
qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr) qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{ {
int rval; int rval;
struct qla_hw_data *ha = vha->hw;
if (ql2xfwloadbin == 2) if (ql2xfwloadbin == 2)
return qla24xx_load_risc(vha, srisc_addr); goto try_blob_fw;
/* /*
* FW Load priority: * FW Load priority:
* 1) Firmware residing in flash. * 1) Firmware residing in flash.
* 2) Firmware via request-firmware interface (.bin file). * 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) if (rval == QLA_SUCCESS)
return rval; 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 void
......
...@@ -1690,6 +1690,9 @@ qla2xxx_scan_start(struct Scsi_Host *shost) ...@@ -1690,6 +1690,9 @@ qla2xxx_scan_start(struct Scsi_Host *shost)
{ {
scsi_qla_host_t *vha = shost_priv(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(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(RSCN_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) ...@@ -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" "Can't create queues, falling back to single"
" queue mode\n"); " queue mode\n");
if (ha->flags.running_gold_fw)
goto skip_dpc;
/* /*
* Startup the kernel thread for this host adapter * 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) ...@@ -1974,6 +1980,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto probe_failed; goto probe_failed;
} }
skip_dpc:
list_add_tail(&base_vha->list, &ha->vp_list); list_add_tail(&base_vha->list, &ha->vp_list);
base_vha->host->irq = ha->pdev->irq; base_vha->host->irq = ha->pdev->irq;
......
...@@ -728,6 +728,9 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) ...@@ -728,6 +728,9 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
if (!ha->flags.port0) if (!ha->flags.port0)
ha->flt_region_npiv_conf = start; ha->flt_region_npiv_conf = start;
break; break;
case FLT_REG_GOLD_FW:
ha->flt_region_gold_fw = start;
break;
} }
} }
goto done; 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