diff options
author | Joe Carnuccio <joe.carnuccio@qlogic.com> | 2009-03-24 12:08:06 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-03 10:22:48 -0400 |
commit | 1d2874de809a14e6780246b99a18bbc0fc0a8f2a (patch) | |
tree | 0f9dc305dc6f802c27bcef6edc607832864b7687 /drivers/scsi/qla2xxx/qla_sup.c | |
parent | b9978769877c6c90c8d6777df13b9ae427af40b7 (diff) |
[SCSI] qla2xxx: Add Flash-Access-Control support for recent ISPs.
Given the low-level interface varies from one flash-part
manufacturer to the next, the Flash-Access-Control (FAC) mailbox
command makes the specific flash type transparent to the driver
by encapsulating a basic set of accessor and update routines.
Use these new routines where applicable by querying FAC opcode
get-sector-size at init-time.
Additional cleanups and
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_sup.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 60 |
1 files changed, 47 insertions, 13 deletions
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 5b24af86aaf0..ff5aa75109fc 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -931,31 +931,41 @@ done: | |||
931 | ha->npiv_info = NULL; | 931 | ha->npiv_info = NULL; |
932 | } | 932 | } |
933 | 933 | ||
934 | static void | 934 | static int |
935 | qla24xx_unprotect_flash(struct qla_hw_data *ha) | 935 | qla24xx_unprotect_flash(scsi_qla_host_t *vha) |
936 | { | 936 | { |
937 | struct qla_hw_data *ha = vha->hw; | ||
937 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 938 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
938 | 939 | ||
940 | if (ha->flags.fac_supported) | ||
941 | return qla81xx_fac_do_write_enable(vha, 1); | ||
942 | |||
939 | /* Enable flash write. */ | 943 | /* Enable flash write. */ |
940 | WRT_REG_DWORD(®->ctrl_status, | 944 | WRT_REG_DWORD(®->ctrl_status, |
941 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); | 945 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); |
942 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ | 946 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ |
943 | 947 | ||
944 | if (!ha->fdt_wrt_disable) | 948 | if (!ha->fdt_wrt_disable) |
945 | return; | 949 | goto done; |
946 | 950 | ||
947 | /* Disable flash write-protection, first clear SR protection bit */ | 951 | /* Disable flash write-protection, first clear SR protection bit */ |
948 | qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0); | 952 | qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0); |
949 | /* Then write zero again to clear remaining SR bits.*/ | 953 | /* Then write zero again to clear remaining SR bits.*/ |
950 | qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0); | 954 | qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0); |
955 | done: | ||
956 | return QLA_SUCCESS; | ||
951 | } | 957 | } |
952 | 958 | ||
953 | static void | 959 | static int |
954 | qla24xx_protect_flash(struct qla_hw_data *ha) | 960 | qla24xx_protect_flash(scsi_qla_host_t *vha) |
955 | { | 961 | { |
956 | uint32_t cnt; | 962 | uint32_t cnt; |
963 | struct qla_hw_data *ha = vha->hw; | ||
957 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 964 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
958 | 965 | ||
966 | if (ha->flags.fac_supported) | ||
967 | return qla81xx_fac_do_write_enable(vha, 0); | ||
968 | |||
959 | if (!ha->fdt_wrt_disable) | 969 | if (!ha->fdt_wrt_disable) |
960 | goto skip_wrt_protect; | 970 | goto skip_wrt_protect; |
961 | 971 | ||
@@ -973,6 +983,26 @@ skip_wrt_protect: | |||
973 | WRT_REG_DWORD(®->ctrl_status, | 983 | WRT_REG_DWORD(®->ctrl_status, |
974 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); | 984 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); |
975 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ | 985 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ |
986 | |||
987 | return QLA_SUCCESS; | ||
988 | } | ||
989 | |||
990 | static int | ||
991 | qla24xx_erase_sector(scsi_qla_host_t *vha, uint32_t fdata) | ||
992 | { | ||
993 | struct qla_hw_data *ha = vha->hw; | ||
994 | uint32_t start, finish; | ||
995 | |||
996 | if (ha->flags.fac_supported) { | ||
997 | start = fdata >> 2; | ||
998 | finish = start + (ha->fdt_block_size >> 2) - 1; | ||
999 | return qla81xx_fac_erase_sector(vha, flash_data_addr(ha, | ||
1000 | start), flash_data_addr(ha, finish)); | ||
1001 | } | ||
1002 | |||
1003 | return qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd, | ||
1004 | (fdata & 0xff00) | ((fdata << 16) & 0xff0000) | | ||
1005 | ((fdata >> 16) & 0xff)); | ||
976 | } | 1006 | } |
977 | 1007 | ||
978 | static int | 1008 | static int |
@@ -987,8 +1017,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | |||
987 | void *optrom = NULL; | 1017 | void *optrom = NULL; |
988 | struct qla_hw_data *ha = vha->hw; | 1018 | struct qla_hw_data *ha = vha->hw; |
989 | 1019 | ||
990 | ret = QLA_SUCCESS; | ||
991 | |||
992 | /* Prepare burst-capable write on supported ISPs. */ | 1020 | /* Prepare burst-capable write on supported ISPs. */ |
993 | if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && !(faddr & 0xfff) && | 1021 | if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && !(faddr & 0xfff) && |
994 | dwords > OPTROM_BURST_DWORDS) { | 1022 | dwords > OPTROM_BURST_DWORDS) { |
@@ -1004,7 +1032,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | |||
1004 | rest_addr = (ha->fdt_block_size >> 2) - 1; | 1032 | rest_addr = (ha->fdt_block_size >> 2) - 1; |
1005 | sec_mask = ~rest_addr; | 1033 | sec_mask = ~rest_addr; |
1006 | 1034 | ||
1007 | qla24xx_unprotect_flash(ha); | 1035 | ret = qla24xx_unprotect_flash(vha); |
1036 | if (ret != QLA_SUCCESS) { | ||
1037 | qla_printk(KERN_WARNING, ha, | ||
1038 | "Unable to unprotect flash for update.\n"); | ||
1039 | goto done; | ||
1040 | } | ||
1008 | 1041 | ||
1009 | for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { | 1042 | for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { |
1010 | fdata = (faddr & sec_mask) << 2; | 1043 | fdata = (faddr & sec_mask) << 2; |
@@ -1017,9 +1050,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | |||
1017 | ha->fdt_unprotect_sec_cmd, | 1050 | ha->fdt_unprotect_sec_cmd, |
1018 | (fdata & 0xff00) | ((fdata << 16) & | 1051 | (fdata & 0xff00) | ((fdata << 16) & |
1019 | 0xff0000) | ((fdata >> 16) & 0xff)); | 1052 | 0xff0000) | ((fdata >> 16) & 0xff)); |
1020 | ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd, | 1053 | ret = qla24xx_erase_sector(vha, fdata); |
1021 | (fdata & 0xff00) |((fdata << 16) & | ||
1022 | 0xff0000) | ((fdata >> 16) & 0xff)); | ||
1023 | if (ret != QLA_SUCCESS) { | 1054 | if (ret != QLA_SUCCESS) { |
1024 | DEBUG9(qla_printk("Unable to erase sector: " | 1055 | DEBUG9(qla_printk("Unable to erase sector: " |
1025 | "address=%x.\n", faddr)); | 1056 | "address=%x.\n", faddr)); |
@@ -1073,8 +1104,11 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, | |||
1073 | 0xff0000) | ((fdata >> 16) & 0xff)); | 1104 | 0xff0000) | ((fdata >> 16) & 0xff)); |
1074 | } | 1105 | } |
1075 | 1106 | ||
1076 | qla24xx_protect_flash(ha); | 1107 | ret = qla24xx_protect_flash(vha); |
1077 | 1108 | if (ret != QLA_SUCCESS) | |
1109 | qla_printk(KERN_WARNING, ha, | ||
1110 | "Unable to protect flash after update.\n"); | ||
1111 | done: | ||
1078 | if (optrom) | 1112 | if (optrom) |
1079 | dma_free_coherent(&ha->pdev->dev, | 1113 | dma_free_coherent(&ha->pdev->dev, |
1080 | OPTROM_BURST_SIZE, optrom, optrom_dma); | 1114 | OPTROM_BURST_SIZE, optrom, optrom_dma); |