aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2006-05-17 18:09:00 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-05-20 10:41:31 -0400
commitd1c61909c05ead100f855e640fba53925d0665ac (patch)
tree2fc533e6e77a7bf2814bff98edb66990fc97a211 /drivers
parented17c71b5d11327efd40666fd621486f964fae4f (diff)
[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>
Diffstat (limited to 'drivers')
-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)
3498 return (rval); 3498 return (rval);
3499} 3499}
3500 3500
3501int
3502qla24xx_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
3501#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) 3583#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
3502 3584
3503int 3585int
@@ -3625,90 +3707,10 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3625 return rval; 3707 return rval;
3626} 3708}
3627 3709
3628int
3629qla24xx_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
3710#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ 3710#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
3711 3711
3712#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"
3713
3712int 3714int
3713qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) 3715qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3714{ 3716{
@@ -3722,6 +3724,8 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3722 blob = qla2x00_request_firmware(ha); 3724 blob = qla2x00_request_firmware(ha);
3723 if (!blob) { 3725 if (!blob) {
3724 qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); 3726 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");
3725 return QLA_FUNCTION_FAILED; 3729 return QLA_FUNCTION_FAILED;
3726 } 3730 }
3727 3731
@@ -3823,7 +3827,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
3823 blob = qla2x00_request_firmware(ha); 3827 blob = qla2x00_request_firmware(ha);
3824 if (!blob) { 3828 if (!blob) {
3825 qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); 3829 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);
3827 } 3837 }
3828 3838
3829 rval = QLA_SUCCESS; 3839 rval = QLA_SUCCESS;