forked from luck/tmp_suning_uos_patched
[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:
parent
ed17c71b5d
commit
d1c61909c0
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user