[SCSI] qla2xxx: Update ISP24xx firwmare loading heuristics.

If firmware image is unavailable via request_firwmare(), then
attempt to load the image (likely out-of-date) stored in flash
memory.

Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Andrew Vasquez 2006-05-17 15:09:00 -07:00 committed by James Bottomley
parent ed17c71b5d
commit d1c61909c0

View File

@ -3498,6 +3498,88 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
return (rval);
}
int
qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
int rval;
int segments, fragment;
uint32_t faddr;
uint32_t *dcode, dlen;
uint32_t risc_addr;
uint32_t risc_size;
uint32_t i;
rval = QLA_SUCCESS;
segments = FA_RISC_CODE_SEGMENTS;
faddr = FA_RISC_CODE_ADDR;
dcode = (uint32_t *)ha->request_ring;
*srisc_addr = 0;
/* Validate firmware image by checking version. */
qla24xx_read_flash_data(ha, dcode, faddr + 4, 4);
for (i = 0; i < 4; i++)
dcode[i] = be32_to_cpu(dcode[i]);
if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
qla_printk(KERN_WARNING, ha,
"Unable to verify integrity of flash firmware image!\n");
qla_printk(KERN_WARNING, ha,
"Firmware data: %08x %08x %08x %08x!\n", dcode[0],
dcode[1], dcode[2], dcode[3]);
return QLA_FUNCTION_FAILED;
}
while (segments && rval == QLA_SUCCESS) {
/* Read segment's load information. */
qla24xx_read_flash_data(ha, dcode, faddr, 4);
risc_addr = be32_to_cpu(dcode[2]);
*srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
risc_size = be32_to_cpu(dcode[3]);
fragment = 0;
while (risc_size > 0 && rval == QLA_SUCCESS) {
dlen = (uint32_t)(ha->fw_transfer_size >> 2);
if (dlen > risc_size)
dlen = risc_size;
DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
"addr %x, number of dwords 0x%x, offset 0x%x.\n",
ha->host_no, risc_addr, dlen, faddr));
qla24xx_read_flash_data(ha, dcode, faddr, dlen);
for (i = 0; i < dlen; i++)
dcode[i] = swab32(dcode[i]);
rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
fragment));
qla_printk(KERN_WARNING, ha,
"[ERROR] Failed to load segment %d of "
"firmware\n", fragment);
break;
}
faddr += dlen;
risc_addr += dlen;
risc_size -= dlen;
fragment++;
}
/* Next segment. */
segments--;
}
return rval;
}
#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
int
@ -3625,90 +3707,10 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
return rval;
}
int
qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
int rval;
int segments, fragment;
uint32_t faddr;
uint32_t *dcode, dlen;
uint32_t risc_addr;
uint32_t risc_size;
uint32_t i;
rval = QLA_SUCCESS;
segments = FA_RISC_CODE_SEGMENTS;
faddr = FA_RISC_CODE_ADDR;
dcode = (uint32_t *)ha->request_ring;
*srisc_addr = 0;
/* Validate firmware image by checking version. */
qla24xx_read_flash_data(ha, dcode, faddr + 4, 4);
for (i = 0; i < 4; i++)
dcode[i] = be32_to_cpu(dcode[i]);
if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
qla_printk(KERN_WARNING, ha,
"Unable to verify integrity of flash firmware image!\n");
qla_printk(KERN_WARNING, ha,
"Firmware data: %08x %08x %08x %08x!\n", dcode[0],
dcode[1], dcode[2], dcode[3]);
return QLA_FUNCTION_FAILED;
}
while (segments && rval == QLA_SUCCESS) {
/* Read segment's load information. */
qla24xx_read_flash_data(ha, dcode, faddr, 4);
risc_addr = be32_to_cpu(dcode[2]);
*srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
risc_size = be32_to_cpu(dcode[3]);
fragment = 0;
while (risc_size > 0 && rval == QLA_SUCCESS) {
dlen = (uint32_t)(ha->fw_transfer_size >> 2);
if (dlen > risc_size)
dlen = risc_size;
DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
"addr %x, number of dwords 0x%x, offset 0x%x.\n",
ha->host_no, risc_addr, dlen, faddr));
qla24xx_read_flash_data(ha, dcode, faddr, dlen);
for (i = 0; i < dlen; i++)
dcode[i] = swab32(dcode[i]);
rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
fragment));
qla_printk(KERN_WARNING, ha,
"[ERROR] Failed to load segment %d of "
"firmware\n", fragment);
break;
}
faddr += dlen;
risc_addr += dlen;
risc_size -= dlen;
fragment++;
}
/* Next segment. */
segments--;
}
return rval;
}
#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"
int
qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
@ -3722,6 +3724,8 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
blob = qla2x00_request_firmware(ha);
if (!blob) {
qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
"from: " QLA_FW_URL ".\n");
return QLA_FUNCTION_FAILED;
}
@ -3823,7 +3827,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
blob = qla2x00_request_firmware(ha);
if (!blob) {
qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
return QLA_FUNCTION_FAILED;
qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
"from: " QLA_FW_URL ".\n");
/* Try to load RISC code from flash. */
qla_printk(KERN_ERR, ha, "Attempting to load (potentially "
"outdated) firmware from flash.\n");
return qla24xx_load_risc_flash(ha, srisc_addr);
}
rval = QLA_SUCCESS;