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
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;
}
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;
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;
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
{
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);
"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
*/
goto probe_failed;
}
+skip_dpc:
list_add_tail(&base_vha->list, &ha->vp_list);
base_vha->host->irq = ha->pdev->irq;