Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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 {
	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;
+1 −0
Original line number Original line Diff line number Diff line
@@ -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;
+25 −8
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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
+7 −0
Original line number Original line Diff line number Diff line
@@ -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)
				"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)
		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;


+3 −0
Original line number Original line Diff line number Diff line
@@ -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;