summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2006-05-17 15:09:00 -0700
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-05-20 09:41:31 -0500
commitd1c61909c05ead100f855e640fba53925d0665ac (patch)
tree2fc533e6e77a7bf2814bff98edb66990fc97a211
parented17c71b5d11327efd40666fd621486f964fae4f (diff)
downloadlinux-d1c61909c05ead100f855e640fba53925d0665ac.tar.bz2
[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>
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c176
1 files changed, 93 insertions, 83 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 89a3fc0595bb..1cf27fe92f4b 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -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;