Skip to content

Commit d1c6190

Browse files
avasquez01James Bottomley
authored andcommitted
[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>
1 parent ed17c71 commit d1c6190

File tree

1 file changed

+93
-83
lines changed

1 file changed

+93
-83
lines changed

drivers/scsi/qla2xxx/qla_init.c

Lines changed: 93 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3498,6 +3498,88 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
34983498
return (rval);
34993499
}
35003500

3501+
int
3502+
qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3503+
{
3504+
int rval;
3505+
int segments, fragment;
3506+
uint32_t faddr;
3507+
uint32_t *dcode, dlen;
3508+
uint32_t risc_addr;
3509+
uint32_t risc_size;
3510+
uint32_t i;
3511+
3512+
rval = QLA_SUCCESS;
3513+
3514+
segments = FA_RISC_CODE_SEGMENTS;
3515+
faddr = FA_RISC_CODE_ADDR;
3516+
dcode = (uint32_t *)ha->request_ring;
3517+
*srisc_addr = 0;
3518+
3519+
/* Validate firmware image by checking version. */
3520+
qla24xx_read_flash_data(ha, dcode, faddr + 4, 4);
3521+
for (i = 0; i < 4; i++)
3522+
dcode[i] = be32_to_cpu(dcode[i]);
3523+
if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
3524+
dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
3525+
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
3526+
dcode[3] == 0)) {
3527+
qla_printk(KERN_WARNING, ha,
3528+
"Unable to verify integrity of flash firmware image!\n");
3529+
qla_printk(KERN_WARNING, ha,
3530+
"Firmware data: %08x %08x %08x %08x!\n", dcode[0],
3531+
dcode[1], dcode[2], dcode[3]);
3532+
3533+
return QLA_FUNCTION_FAILED;
3534+
}
3535+
3536+
while (segments && rval == QLA_SUCCESS) {
3537+
/* Read segment's load information. */
3538+
qla24xx_read_flash_data(ha, dcode, faddr, 4);
3539+
3540+
risc_addr = be32_to_cpu(dcode[2]);
3541+
*srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
3542+
risc_size = be32_to_cpu(dcode[3]);
3543+
3544+
fragment = 0;
3545+
while (risc_size > 0 && rval == QLA_SUCCESS) {
3546+
dlen = (uint32_t)(ha->fw_transfer_size >> 2);
3547+
if (dlen > risc_size)
3548+
dlen = risc_size;
3549+
3550+
DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
3551+
"addr %x, number of dwords 0x%x, offset 0x%x.\n",
3552+
ha->host_no, risc_addr, dlen, faddr));
3553+
3554+
qla24xx_read_flash_data(ha, dcode, faddr, dlen);
3555+
for (i = 0; i < dlen; i++)
3556+
dcode[i] = swab32(dcode[i]);
3557+
3558+
rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
3559+
dlen);
3560+
if (rval) {
3561+
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
3562+
"segment %d of firmware\n", ha->host_no,
3563+
fragment));
3564+
qla_printk(KERN_WARNING, ha,
3565+
"[ERROR] Failed to load segment %d of "
3566+
"firmware\n", fragment);
3567+
break;
3568+
}
3569+
3570+
faddr += dlen;
3571+
risc_addr += dlen;
3572+
risc_size -= dlen;
3573+
fragment++;
3574+
}
3575+
3576+
/* Next segment. */
3577+
segments--;
3578+
}
3579+
3580+
return rval;
3581+
}
3582+
35013583
#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
35023584

35033585
int
@@ -3625,90 +3707,10 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
36253707
return rval;
36263708
}
36273709

3628-
int
3629-
qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3630-
{
3631-
int rval;
3632-
int segments, fragment;
3633-
uint32_t faddr;
3634-
uint32_t *dcode, dlen;
3635-
uint32_t risc_addr;
3636-
uint32_t risc_size;
3637-
uint32_t i;
3638-
3639-
rval = QLA_SUCCESS;
3640-
3641-
segments = FA_RISC_CODE_SEGMENTS;
3642-
faddr = FA_RISC_CODE_ADDR;
3643-
dcode = (uint32_t *)ha->request_ring;
3644-
*srisc_addr = 0;
3645-
3646-
/* Validate firmware image by checking version. */
3647-
qla24xx_read_flash_data(ha, dcode, faddr + 4, 4);
3648-
for (i = 0; i < 4; i++)
3649-
dcode[i] = be32_to_cpu(dcode[i]);
3650-
if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
3651-
dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
3652-
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
3653-
dcode[3] == 0)) {
3654-
qla_printk(KERN_WARNING, ha,
3655-
"Unable to verify integrity of flash firmware image!\n");
3656-
qla_printk(KERN_WARNING, ha,
3657-
"Firmware data: %08x %08x %08x %08x!\n", dcode[0],
3658-
dcode[1], dcode[2], dcode[3]);
3659-
3660-
return QLA_FUNCTION_FAILED;
3661-
}
3662-
3663-
while (segments && rval == QLA_SUCCESS) {
3664-
/* Read segment's load information. */
3665-
qla24xx_read_flash_data(ha, dcode, faddr, 4);
3666-
3667-
risc_addr = be32_to_cpu(dcode[2]);
3668-
*srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
3669-
risc_size = be32_to_cpu(dcode[3]);
3670-
3671-
fragment = 0;
3672-
while (risc_size > 0 && rval == QLA_SUCCESS) {
3673-
dlen = (uint32_t)(ha->fw_transfer_size >> 2);
3674-
if (dlen > risc_size)
3675-
dlen = risc_size;
3676-
3677-
DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
3678-
"addr %x, number of dwords 0x%x, offset 0x%x.\n",
3679-
ha->host_no, risc_addr, dlen, faddr));
3680-
3681-
qla24xx_read_flash_data(ha, dcode, faddr, dlen);
3682-
for (i = 0; i < dlen; i++)
3683-
dcode[i] = swab32(dcode[i]);
3684-
3685-
rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
3686-
dlen);
3687-
if (rval) {
3688-
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
3689-
"segment %d of firmware\n", ha->host_no,
3690-
fragment));
3691-
qla_printk(KERN_WARNING, ha,
3692-
"[ERROR] Failed to load segment %d of "
3693-
"firmware\n", fragment);
3694-
break;
3695-
}
3696-
3697-
faddr += dlen;
3698-
risc_addr += dlen;
3699-
risc_size -= dlen;
3700-
fragment++;
3701-
}
3702-
3703-
/* Next segment. */
3704-
segments--;
3705-
}
3706-
3707-
return rval;
3708-
}
3709-
37103710
#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
37113711

3712+
#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"
3713+
37123714
int
37133715
qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
37143716
{
@@ -3722,6 +3724,8 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
37223724
blob = qla2x00_request_firmware(ha);
37233725
if (!blob) {
37243726
qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
3727+
qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
3728+
"from: " QLA_FW_URL ".\n");
37253729
return QLA_FUNCTION_FAILED;
37263730
}
37273731

@@ -3823,7 +3827,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
38233827
blob = qla2x00_request_firmware(ha);
38243828
if (!blob) {
38253829
qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
3826-
return QLA_FUNCTION_FAILED;
3830+
qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
3831+
"from: " QLA_FW_URL ".\n");
3832+
3833+
/* Try to load RISC code from flash. */
3834+
qla_printk(KERN_ERR, ha, "Attempting to load (potentially "
3835+
"outdated) firmware from flash.\n");
3836+
return qla24xx_load_risc_flash(ha, srisc_addr);
38273837
}
38283838

38293839
rval = QLA_SUCCESS;

0 commit comments

Comments
 (0)