diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2006-05-17 18:09:00 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-05-20 10:41:31 -0400 |
commit | d1c61909c05ead100f855e640fba53925d0665ac (patch) | |
tree | 2fc533e6e77a7bf2814bff98edb66990fc97a211 /drivers/scsi/qla2xxx/qla_init.c | |
parent | ed17c71b5d11327efd40666fd621486f964fae4f (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/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 176 |
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 | ||
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 | |||
3501 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) | 3583 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) |
3502 | 3584 | ||
3503 | int | 3585 | int |
@@ -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 | ||
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 | |||
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 | |||
3712 | int | 3714 | int |
3713 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | 3715 | qla2x00_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; |