diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2005-11-09 18:49:04 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-12-13 20:11:16 -0500 |
commit | 5433383ef33ed40c9c8a86a4355da344234af2a5 (patch) | |
tree | 8d82c620fe6faadfa805fb465d5beb67946133c7 /drivers/scsi/qla2xxx/qla_init.c | |
parent | 26a68019c86e1d1782984a7a5babff762cde1501 (diff) |
[SCSI] qla2xxx: Add full firmware(-request) hotplug support for all ISPs.
Transition driver to exclusively use the request_firmware()
interfaces to retrieve firmware-blobs from user-space. This
will be the default behaviour going forward until the
embedded firmware-binary images are removed from the
upstream kernel.
Upon request, the driver caches the firmware image until the
driver is unloaded.
NOTE: The option is present to allow the user to continue to
use the firmware-loader modules, but, should be considered
deprecated.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Rejections fixed up and
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 | 189 |
1 files changed, 137 insertions, 52 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 2d720121a0d3..13e2aaf56769 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -8,7 +8,6 @@ | |||
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/vmalloc.h> | 10 | #include <linux/vmalloc.h> |
11 | #include <linux/firmware.h> | ||
12 | #include <scsi/scsi_transport_fc.h> | 11 | #include <scsi/scsi_transport_fc.h> |
13 | 12 | ||
14 | #include "qla_devtbl.h" | 13 | #include "qla_devtbl.h" |
@@ -3484,17 +3483,16 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3484 | return (rval); | 3483 | return (rval); |
3485 | } | 3484 | } |
3486 | 3485 | ||
3486 | #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) | ||
3487 | |||
3487 | int | 3488 | int |
3488 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | 3489 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) |
3489 | { | 3490 | { |
3490 | int rval; | 3491 | int rval, num, i; |
3491 | uint16_t cnt; | 3492 | uint32_t cnt; |
3492 | uint16_t *risc_code; | 3493 | uint16_t *risc_code; |
3493 | unsigned long risc_address; | 3494 | uint32_t risc_addr, risc_size; |
3494 | unsigned long risc_code_size; | 3495 | uint16_t *req_ring; |
3495 | int num; | ||
3496 | int i; | ||
3497 | uint16_t *req_ring; | ||
3498 | struct qla_fw_info *fw_iter; | 3496 | struct qla_fw_info *fw_iter; |
3499 | 3497 | ||
3500 | rval = QLA_SUCCESS; | 3498 | rval = QLA_SUCCESS; |
@@ -3504,37 +3502,29 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3504 | *srisc_addr = *ha->brd_info->fw_info->fwstart; | 3502 | *srisc_addr = *ha->brd_info->fw_info->fwstart; |
3505 | while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { | 3503 | while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { |
3506 | risc_code = fw_iter->fwcode; | 3504 | risc_code = fw_iter->fwcode; |
3507 | risc_code_size = *fw_iter->fwlen; | 3505 | risc_size = *fw_iter->fwlen; |
3508 | 3506 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) | |
3509 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { | 3507 | risc_addr = *fw_iter->fwstart; |
3510 | risc_address = *fw_iter->fwstart; | 3508 | else |
3511 | } else { | 3509 | risc_addr = *fw_iter->lfwstart; |
3512 | /* Extended address */ | ||
3513 | risc_address = *fw_iter->lfwstart; | ||
3514 | } | ||
3515 | 3510 | ||
3516 | num = 0; | 3511 | num = 0; |
3517 | rval = 0; | 3512 | rval = 0; |
3518 | while (risc_code_size > 0 && !rval) { | 3513 | while (risc_size > 0 && !rval) { |
3519 | cnt = (uint16_t)(ha->fw_transfer_size >> 1); | 3514 | cnt = (uint16_t)(ha->fw_transfer_size >> 1); |
3520 | if (cnt > risc_code_size) | 3515 | if (cnt > risc_size) |
3521 | cnt = risc_code_size; | 3516 | cnt = risc_size; |
3522 | 3517 | ||
3523 | DEBUG7(printk("scsi(%ld): Loading risc segment@ " | 3518 | DEBUG7(printk("scsi(%ld): Loading risc segment@ " |
3524 | "addr %p, number of bytes 0x%x, offset 0x%lx.\n", | 3519 | "addr %p, number of bytes 0x%x, offset 0x%lx.\n", |
3525 | ha->host_no, risc_code, cnt, risc_address)); | 3520 | ha->host_no, risc_code, cnt, risc_addr)); |
3526 | 3521 | ||
3527 | req_ring = (uint16_t *)ha->request_ring; | 3522 | req_ring = (uint16_t *)ha->request_ring; |
3528 | for (i = 0; i < cnt; i++) | 3523 | for (i = 0; i < cnt; i++) |
3529 | req_ring[i] = cpu_to_le16(risc_code[i]); | 3524 | req_ring[i] = cpu_to_le16(risc_code[i]); |
3530 | 3525 | ||
3531 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { | 3526 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, |
3532 | rval = qla2x00_load_ram(ha, ha->request_dma, | 3527 | cnt); |
3533 | risc_address, cnt); | ||
3534 | } else { | ||
3535 | rval = qla2x00_load_ram_ext(ha, | ||
3536 | ha->request_dma, risc_address, cnt); | ||
3537 | } | ||
3538 | if (rval) { | 3528 | if (rval) { |
3539 | DEBUG(printk("scsi(%ld): [ERROR] Failed to " | 3529 | DEBUG(printk("scsi(%ld): [ERROR] Failed to " |
3540 | "load segment %d of firmware\n", | 3530 | "load segment %d of firmware\n", |
@@ -3548,16 +3538,15 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3548 | } | 3538 | } |
3549 | 3539 | ||
3550 | risc_code += cnt; | 3540 | risc_code += cnt; |
3551 | risc_address += cnt; | 3541 | risc_addr += cnt; |
3552 | risc_code_size -= cnt; | 3542 | risc_size -= cnt; |
3553 | num++; | 3543 | num++; |
3554 | } | 3544 | } |
3555 | 3545 | ||
3556 | /* Next firmware sequence */ | 3546 | /* Next firmware sequence */ |
3557 | fw_iter++; | 3547 | fw_iter++; |
3558 | } | 3548 | } |
3559 | 3549 | return rval; | |
3560 | return (rval); | ||
3561 | } | 3550 | } |
3562 | 3551 | ||
3563 | int | 3552 | int |
@@ -3642,8 +3631,108 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3642 | return rval; | 3631 | return rval; |
3643 | } | 3632 | } |
3644 | 3633 | ||
3634 | #else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ | ||
3635 | |||
3645 | int | 3636 | int |
3646 | qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | 3637 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) |
3638 | { | ||
3639 | int rval; | ||
3640 | int i, fragment; | ||
3641 | uint16_t *wcode, *fwcode; | ||
3642 | uint32_t risc_addr, risc_size, fwclen, wlen, *seg; | ||
3643 | struct fw_blob *blob; | ||
3644 | |||
3645 | /* Load firmware blob. */ | ||
3646 | blob = qla2x00_request_firmware(ha); | ||
3647 | if (!blob) { | ||
3648 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); | ||
3649 | return QLA_FUNCTION_FAILED; | ||
3650 | } | ||
3651 | |||
3652 | rval = QLA_SUCCESS; | ||
3653 | |||
3654 | wcode = (uint16_t *)ha->request_ring; | ||
3655 | *srisc_addr = 0; | ||
3656 | fwcode = (uint16_t *)blob->fw->data; | ||
3657 | fwclen = 0; | ||
3658 | |||
3659 | /* Validate firmware image by checking version. */ | ||
3660 | if (blob->fw->size < 8 * sizeof(uint16_t)) { | ||
3661 | qla_printk(KERN_WARNING, ha, | ||
3662 | "Unable to verify integrity of firmware image (%Zd)!\n", | ||
3663 | blob->fw->size); | ||
3664 | goto fail_fw_integrity; | ||
3665 | } | ||
3666 | for (i = 0; i < 4; i++) | ||
3667 | wcode[i] = be16_to_cpu(fwcode[i + 4]); | ||
3668 | if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff && | ||
3669 | wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 && | ||
3670 | wcode[2] == 0 && wcode[3] == 0)) { | ||
3671 | qla_printk(KERN_WARNING, ha, | ||
3672 | "Unable to verify integrity of firmware image!\n"); | ||
3673 | qla_printk(KERN_WARNING, ha, | ||
3674 | "Firmware data: %04x %04x %04x %04x!\n", wcode[0], | ||
3675 | wcode[1], wcode[2], wcode[3]); | ||
3676 | goto fail_fw_integrity; | ||
3677 | } | ||
3678 | |||
3679 | seg = blob->segs; | ||
3680 | while (*seg && rval == QLA_SUCCESS) { | ||
3681 | risc_addr = *seg; | ||
3682 | *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr; | ||
3683 | risc_size = be16_to_cpu(fwcode[3]); | ||
3684 | |||
3685 | /* Validate firmware image size. */ | ||
3686 | fwclen += risc_size * sizeof(uint16_t); | ||
3687 | if (blob->fw->size < fwclen) { | ||
3688 | qla_printk(KERN_WARNING, ha, | ||
3689 | "Unable to verify integrity of firmware image " | ||
3690 | "(%Zd)!\n", blob->fw->size); | ||
3691 | goto fail_fw_integrity; | ||
3692 | } | ||
3693 | |||
3694 | fragment = 0; | ||
3695 | while (risc_size > 0 && rval == QLA_SUCCESS) { | ||
3696 | wlen = (uint16_t)(ha->fw_transfer_size >> 1); | ||
3697 | if (wlen > risc_size) | ||
3698 | wlen = risc_size; | ||
3699 | |||
3700 | DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " | ||
3701 | "addr %x, number of words 0x%x.\n", ha->host_no, | ||
3702 | risc_addr, wlen)); | ||
3703 | |||
3704 | for (i = 0; i < wlen; i++) | ||
3705 | wcode[i] = swab16(fwcode[i]); | ||
3706 | |||
3707 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, | ||
3708 | wlen); | ||
3709 | if (rval) { | ||
3710 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " | ||
3711 | "segment %d of firmware\n", ha->host_no, | ||
3712 | fragment)); | ||
3713 | qla_printk(KERN_WARNING, ha, | ||
3714 | "[ERROR] Failed to load segment %d of " | ||
3715 | "firmware\n", fragment); | ||
3716 | break; | ||
3717 | } | ||
3718 | |||
3719 | fwcode += wlen; | ||
3720 | risc_addr += wlen; | ||
3721 | risc_size -= wlen; | ||
3722 | fragment++; | ||
3723 | } | ||
3724 | |||
3725 | /* Next segment. */ | ||
3726 | seg++; | ||
3727 | } | ||
3728 | return rval; | ||
3729 | |||
3730 | fail_fw_integrity: | ||
3731 | return QLA_FUNCTION_FAILED; | ||
3732 | } | ||
3733 | |||
3734 | int | ||
3735 | qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3647 | { | 3736 | { |
3648 | int rval; | 3737 | int rval; |
3649 | int segments, fragment; | 3738 | int segments, fragment; |
@@ -3651,14 +3740,13 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3651 | uint32_t risc_addr; | 3740 | uint32_t risc_addr; |
3652 | uint32_t risc_size; | 3741 | uint32_t risc_size; |
3653 | uint32_t i; | 3742 | uint32_t i; |
3654 | const struct firmware *fw_entry; | 3743 | struct fw_blob *blob; |
3655 | uint32_t *fwcode, fwclen; | 3744 | uint32_t *fwcode, fwclen; |
3656 | 3745 | ||
3657 | if (request_firmware(&fw_entry, ha->brd_info->fw_fname, | 3746 | /* Load firmware blob. */ |
3658 | &ha->pdev->dev)) { | 3747 | blob = qla2x00_request_firmware(ha); |
3659 | qla_printk(KERN_ERR, ha, | 3748 | if (!blob) { |
3660 | "Firmware image file not available: '%s'\n", | 3749 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); |
3661 | ha->brd_info->fw_fname); | ||
3662 | return QLA_FUNCTION_FAILED; | 3750 | return QLA_FUNCTION_FAILED; |
3663 | } | 3751 | } |
3664 | 3752 | ||
@@ -3667,14 +3755,14 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3667 | segments = FA_RISC_CODE_SEGMENTS; | 3755 | segments = FA_RISC_CODE_SEGMENTS; |
3668 | dcode = (uint32_t *)ha->request_ring; | 3756 | dcode = (uint32_t *)ha->request_ring; |
3669 | *srisc_addr = 0; | 3757 | *srisc_addr = 0; |
3670 | fwcode = (uint32_t *)fw_entry->data; | 3758 | fwcode = (uint32_t *)blob->fw->data; |
3671 | fwclen = 0; | 3759 | fwclen = 0; |
3672 | 3760 | ||
3673 | /* Validate firmware image by checking version. */ | 3761 | /* Validate firmware image by checking version. */ |
3674 | if (fw_entry->size < 8 * sizeof(uint32_t)) { | 3762 | if (blob->fw->size < 8 * sizeof(uint32_t)) { |
3675 | qla_printk(KERN_WARNING, ha, | 3763 | qla_printk(KERN_WARNING, ha, |
3676 | "Unable to verify integrity of flash firmware image " | 3764 | "Unable to verify integrity of firmware image (%Zd)!\n", |
3677 | "(%Zd)!\n", fw_entry->size); | 3765 | blob->fw->size); |
3678 | goto fail_fw_integrity; | 3766 | goto fail_fw_integrity; |
3679 | } | 3767 | } |
3680 | for (i = 0; i < 4; i++) | 3768 | for (i = 0; i < 4; i++) |
@@ -3684,7 +3772,7 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3684 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 3772 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
3685 | dcode[3] == 0)) { | 3773 | dcode[3] == 0)) { |
3686 | qla_printk(KERN_WARNING, ha, | 3774 | qla_printk(KERN_WARNING, ha, |
3687 | "Unable to verify integrity of flash firmware image!\n"); | 3775 | "Unable to verify integrity of firmware image!\n"); |
3688 | qla_printk(KERN_WARNING, ha, | 3776 | qla_printk(KERN_WARNING, ha, |
3689 | "Firmware data: %08x %08x %08x %08x!\n", dcode[0], | 3777 | "Firmware data: %08x %08x %08x %08x!\n", dcode[0], |
3690 | dcode[1], dcode[2], dcode[3]); | 3778 | dcode[1], dcode[2], dcode[3]); |
@@ -3698,10 +3786,11 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3698 | 3786 | ||
3699 | /* Validate firmware image size. */ | 3787 | /* Validate firmware image size. */ |
3700 | fwclen += risc_size * sizeof(uint32_t); | 3788 | fwclen += risc_size * sizeof(uint32_t); |
3701 | if (fw_entry->size < fwclen) { | 3789 | if (blob->fw->size < fwclen) { |
3702 | qla_printk(KERN_WARNING, ha, | 3790 | qla_printk(KERN_WARNING, ha, |
3703 | "Unable to verify integrity of flash firmware " | 3791 | "Unable to verify integrity of firmware image " |
3704 | "image (%Zd)!\n", fw_entry->size); | 3792 | "(%Zd)!\n", blob->fw->size); |
3793 | |||
3705 | goto fail_fw_integrity; | 3794 | goto fail_fw_integrity; |
3706 | } | 3795 | } |
3707 | 3796 | ||
@@ -3739,13 +3828,9 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3739 | /* Next segment. */ | 3828 | /* Next segment. */ |
3740 | segments--; | 3829 | segments--; |
3741 | } | 3830 | } |
3742 | |||
3743 | release_firmware(fw_entry); | ||
3744 | return rval; | 3831 | return rval; |
3745 | 3832 | ||
3746 | fail_fw_integrity: | 3833 | fail_fw_integrity: |
3747 | |||
3748 | release_firmware(fw_entry); | ||
3749 | return QLA_FUNCTION_FAILED; | 3834 | return QLA_FUNCTION_FAILED; |
3750 | |||
3751 | } | 3835 | } |
3836 | #endif | ||