diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 248 |
1 files changed, 197 insertions, 51 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index c46d2469b85f..7d973bd9022b 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,76 @@ 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 | } |
3549 | return rval; | ||
3550 | } | ||
3559 | 3551 | ||
3560 | return (rval); | 3552 | int |
3553 | qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3554 | { | ||
3555 | int rval, num, i; | ||
3556 | uint32_t cnt; | ||
3557 | uint32_t *risc_code; | ||
3558 | uint32_t risc_addr, risc_size; | ||
3559 | uint32_t *req_ring; | ||
3560 | struct qla_fw_info *fw_iter; | ||
3561 | |||
3562 | rval = QLA_SUCCESS; | ||
3563 | |||
3564 | /* Load firmware sequences */ | ||
3565 | fw_iter = ha->brd_info->fw_info; | ||
3566 | *srisc_addr = *((uint32_t *)fw_iter->lfwstart); | ||
3567 | while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { | ||
3568 | risc_code = (uint32_t *)fw_iter->fwcode; | ||
3569 | risc_size = *((uint32_t *)fw_iter->fwlen); | ||
3570 | risc_addr = *((uint32_t *)fw_iter->lfwstart); | ||
3571 | |||
3572 | num = 0; | ||
3573 | rval = 0; | ||
3574 | while (risc_size > 0 && !rval) { | ||
3575 | cnt = (uint32_t)(ha->fw_transfer_size >> 2); | ||
3576 | if (cnt > risc_size) | ||
3577 | cnt = risc_size; | ||
3578 | |||
3579 | DEBUG7(printk("scsi(%ld): Loading risc segment@ " | ||
3580 | "addr %p, number of bytes 0x%x, offset 0x%lx.\n", | ||
3581 | ha->host_no, risc_code, cnt, risc_addr)); | ||
3582 | |||
3583 | req_ring = (uint32_t *)ha->request_ring; | ||
3584 | for (i = 0; i < cnt; i++) | ||
3585 | req_ring[i] = cpu_to_le32(risc_code[i]); | ||
3586 | |||
3587 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, | ||
3588 | cnt); | ||
3589 | if (rval) { | ||
3590 | DEBUG(printk("scsi(%ld): [ERROR] Failed to " | ||
3591 | "load segment %d of firmware\n", | ||
3592 | ha->host_no, num)); | ||
3593 | qla_printk(KERN_WARNING, ha, | ||
3594 | "[ERROR] Failed to load segment %d of " | ||
3595 | "firmware\n", num); | ||
3596 | |||
3597 | qla2x00_dump_regs(ha); | ||
3598 | break; | ||
3599 | } | ||
3600 | |||
3601 | risc_code += cnt; | ||
3602 | risc_addr += cnt; | ||
3603 | risc_size -= cnt; | ||
3604 | num++; | ||
3605 | } | ||
3606 | |||
3607 | /* Next firmware sequence */ | ||
3608 | fw_iter++; | ||
3609 | } | ||
3610 | return rval; | ||
3561 | } | 3611 | } |
3562 | 3612 | ||
3563 | int | 3613 | int |
@@ -3642,8 +3692,108 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3642 | return rval; | 3692 | return rval; |
3643 | } | 3693 | } |
3644 | 3694 | ||
3695 | #else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ | ||
3696 | |||
3645 | int | 3697 | int |
3646 | qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | 3698 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) |
3699 | { | ||
3700 | int rval; | ||
3701 | int i, fragment; | ||
3702 | uint16_t *wcode, *fwcode; | ||
3703 | uint32_t risc_addr, risc_size, fwclen, wlen, *seg; | ||
3704 | struct fw_blob *blob; | ||
3705 | |||
3706 | /* Load firmware blob. */ | ||
3707 | blob = qla2x00_request_firmware(ha); | ||
3708 | if (!blob) { | ||
3709 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); | ||
3710 | return QLA_FUNCTION_FAILED; | ||
3711 | } | ||
3712 | |||
3713 | rval = QLA_SUCCESS; | ||
3714 | |||
3715 | wcode = (uint16_t *)ha->request_ring; | ||
3716 | *srisc_addr = 0; | ||
3717 | fwcode = (uint16_t *)blob->fw->data; | ||
3718 | fwclen = 0; | ||
3719 | |||
3720 | /* Validate firmware image by checking version. */ | ||
3721 | if (blob->fw->size < 8 * sizeof(uint16_t)) { | ||
3722 | qla_printk(KERN_WARNING, ha, | ||
3723 | "Unable to verify integrity of firmware image (%Zd)!\n", | ||
3724 | blob->fw->size); | ||
3725 | goto fail_fw_integrity; | ||
3726 | } | ||
3727 | for (i = 0; i < 4; i++) | ||
3728 | wcode[i] = be16_to_cpu(fwcode[i + 4]); | ||
3729 | if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff && | ||
3730 | wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 && | ||
3731 | wcode[2] == 0 && wcode[3] == 0)) { | ||
3732 | qla_printk(KERN_WARNING, ha, | ||
3733 | "Unable to verify integrity of firmware image!\n"); | ||
3734 | qla_printk(KERN_WARNING, ha, | ||
3735 | "Firmware data: %04x %04x %04x %04x!\n", wcode[0], | ||
3736 | wcode[1], wcode[2], wcode[3]); | ||
3737 | goto fail_fw_integrity; | ||
3738 | } | ||
3739 | |||
3740 | seg = blob->segs; | ||
3741 | while (*seg && rval == QLA_SUCCESS) { | ||
3742 | risc_addr = *seg; | ||
3743 | *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr; | ||
3744 | risc_size = be16_to_cpu(fwcode[3]); | ||
3745 | |||
3746 | /* Validate firmware image size. */ | ||
3747 | fwclen += risc_size * sizeof(uint16_t); | ||
3748 | if (blob->fw->size < fwclen) { | ||
3749 | qla_printk(KERN_WARNING, ha, | ||
3750 | "Unable to verify integrity of firmware image " | ||
3751 | "(%Zd)!\n", blob->fw->size); | ||
3752 | goto fail_fw_integrity; | ||
3753 | } | ||
3754 | |||
3755 | fragment = 0; | ||
3756 | while (risc_size > 0 && rval == QLA_SUCCESS) { | ||
3757 | wlen = (uint16_t)(ha->fw_transfer_size >> 1); | ||
3758 | if (wlen > risc_size) | ||
3759 | wlen = risc_size; | ||
3760 | |||
3761 | DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " | ||
3762 | "addr %x, number of words 0x%x.\n", ha->host_no, | ||
3763 | risc_addr, wlen)); | ||
3764 | |||
3765 | for (i = 0; i < wlen; i++) | ||
3766 | wcode[i] = swab16(fwcode[i]); | ||
3767 | |||
3768 | rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, | ||
3769 | wlen); | ||
3770 | if (rval) { | ||
3771 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " | ||
3772 | "segment %d of firmware\n", ha->host_no, | ||
3773 | fragment)); | ||
3774 | qla_printk(KERN_WARNING, ha, | ||
3775 | "[ERROR] Failed to load segment %d of " | ||
3776 | "firmware\n", fragment); | ||
3777 | break; | ||
3778 | } | ||
3779 | |||
3780 | fwcode += wlen; | ||
3781 | risc_addr += wlen; | ||
3782 | risc_size -= wlen; | ||
3783 | fragment++; | ||
3784 | } | ||
3785 | |||
3786 | /* Next segment. */ | ||
3787 | seg++; | ||
3788 | } | ||
3789 | return rval; | ||
3790 | |||
3791 | fail_fw_integrity: | ||
3792 | return QLA_FUNCTION_FAILED; | ||
3793 | } | ||
3794 | |||
3795 | int | ||
3796 | qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3647 | { | 3797 | { |
3648 | int rval; | 3798 | int rval; |
3649 | int segments, fragment; | 3799 | int segments, fragment; |
@@ -3651,14 +3801,13 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3651 | uint32_t risc_addr; | 3801 | uint32_t risc_addr; |
3652 | uint32_t risc_size; | 3802 | uint32_t risc_size; |
3653 | uint32_t i; | 3803 | uint32_t i; |
3654 | const struct firmware *fw_entry; | 3804 | struct fw_blob *blob; |
3655 | uint32_t *fwcode, fwclen; | 3805 | uint32_t *fwcode, fwclen; |
3656 | 3806 | ||
3657 | if (request_firmware(&fw_entry, ha->brd_info->fw_fname, | 3807 | /* Load firmware blob. */ |
3658 | &ha->pdev->dev)) { | 3808 | blob = qla2x00_request_firmware(ha); |
3659 | qla_printk(KERN_ERR, ha, | 3809 | if (!blob) { |
3660 | "Firmware image file not available: '%s'\n", | 3810 | qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); |
3661 | ha->brd_info->fw_fname); | ||
3662 | return QLA_FUNCTION_FAILED; | 3811 | return QLA_FUNCTION_FAILED; |
3663 | } | 3812 | } |
3664 | 3813 | ||
@@ -3667,14 +3816,14 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3667 | segments = FA_RISC_CODE_SEGMENTS; | 3816 | segments = FA_RISC_CODE_SEGMENTS; |
3668 | dcode = (uint32_t *)ha->request_ring; | 3817 | dcode = (uint32_t *)ha->request_ring; |
3669 | *srisc_addr = 0; | 3818 | *srisc_addr = 0; |
3670 | fwcode = (uint32_t *)fw_entry->data; | 3819 | fwcode = (uint32_t *)blob->fw->data; |
3671 | fwclen = 0; | 3820 | fwclen = 0; |
3672 | 3821 | ||
3673 | /* Validate firmware image by checking version. */ | 3822 | /* Validate firmware image by checking version. */ |
3674 | if (fw_entry->size < 8 * sizeof(uint32_t)) { | 3823 | if (blob->fw->size < 8 * sizeof(uint32_t)) { |
3675 | qla_printk(KERN_WARNING, ha, | 3824 | qla_printk(KERN_WARNING, ha, |
3676 | "Unable to verify integrity of flash firmware image " | 3825 | "Unable to verify integrity of firmware image (%Zd)!\n", |
3677 | "(%Zd)!\n", fw_entry->size); | 3826 | blob->fw->size); |
3678 | goto fail_fw_integrity; | 3827 | goto fail_fw_integrity; |
3679 | } | 3828 | } |
3680 | for (i = 0; i < 4; i++) | 3829 | for (i = 0; i < 4; i++) |
@@ -3684,7 +3833,7 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3684 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 3833 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
3685 | dcode[3] == 0)) { | 3834 | dcode[3] == 0)) { |
3686 | qla_printk(KERN_WARNING, ha, | 3835 | qla_printk(KERN_WARNING, ha, |
3687 | "Unable to verify integrity of flash firmware image!\n"); | 3836 | "Unable to verify integrity of firmware image!\n"); |
3688 | qla_printk(KERN_WARNING, ha, | 3837 | qla_printk(KERN_WARNING, ha, |
3689 | "Firmware data: %08x %08x %08x %08x!\n", dcode[0], | 3838 | "Firmware data: %08x %08x %08x %08x!\n", dcode[0], |
3690 | dcode[1], dcode[2], dcode[3]); | 3839 | dcode[1], dcode[2], dcode[3]); |
@@ -3698,10 +3847,11 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3698 | 3847 | ||
3699 | /* Validate firmware image size. */ | 3848 | /* Validate firmware image size. */ |
3700 | fwclen += risc_size * sizeof(uint32_t); | 3849 | fwclen += risc_size * sizeof(uint32_t); |
3701 | if (fw_entry->size < fwclen) { | 3850 | if (blob->fw->size < fwclen) { |
3702 | qla_printk(KERN_WARNING, ha, | 3851 | qla_printk(KERN_WARNING, ha, |
3703 | "Unable to verify integrity of flash firmware " | 3852 | "Unable to verify integrity of firmware image " |
3704 | "image (%Zd)!\n", fw_entry->size); | 3853 | "(%Zd)!\n", blob->fw->size); |
3854 | |||
3705 | goto fail_fw_integrity; | 3855 | goto fail_fw_integrity; |
3706 | } | 3856 | } |
3707 | 3857 | ||
@@ -3739,13 +3889,9 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3739 | /* Next segment. */ | 3889 | /* Next segment. */ |
3740 | segments--; | 3890 | segments--; |
3741 | } | 3891 | } |
3742 | |||
3743 | release_firmware(fw_entry); | ||
3744 | return rval; | 3892 | return rval; |
3745 | 3893 | ||
3746 | fail_fw_integrity: | 3894 | fail_fw_integrity: |
3747 | |||
3748 | release_firmware(fw_entry); | ||
3749 | return QLA_FUNCTION_FAILED; | 3895 | return QLA_FUNCTION_FAILED; |
3750 | |||
3751 | } | 3896 | } |
3897 | #endif | ||