diff options
author | Joe Carnuccio <joe.carnuccio@qlogic.com> | 2009-03-24 09:08:06 -0700 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-03 09:22:48 -0500 |
commit | 1d2874de809a14e6780246b99a18bbc0fc0a8f2a (patch) | |
tree | 0f9dc305dc6f802c27bcef6edc607832864b7687 /drivers/scsi/qla2xxx/qla_sup.c | |
parent | b9978769877c6c90c8d6777df13b9ae427af40b7 (diff) | |
download | blackbird-op-linux-1d2874de809a14e6780246b99a18bbc0fc0a8f2a.tar.gz blackbird-op-linux-1d2874de809a14e6780246b99a18bbc0fc0a8f2a.zip |
[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: ha->npiv_info = NULL; } -static void -qla24xx_unprotect_flash(struct qla_hw_data *ha) +static int +qla24xx_unprotect_flash(scsi_qla_host_t *vha) { + struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + if (ha->flags.fac_supported) + return qla81xx_fac_do_write_enable(vha, 1); + /* Enable flash write. */ WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ if (!ha->fdt_wrt_disable) - return; + goto done; /* Disable flash write-protection, first clear SR protection bit */ qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0); /* Then write zero again to clear remaining SR bits.*/ qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0); +done: + return QLA_SUCCESS; } -static void -qla24xx_protect_flash(struct qla_hw_data *ha) +static int +qla24xx_protect_flash(scsi_qla_host_t *vha) { uint32_t cnt; + struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + if (ha->flags.fac_supported) + return qla81xx_fac_do_write_enable(vha, 0); + if (!ha->fdt_wrt_disable) goto skip_wrt_protect; @@ -973,6 +983,26 @@ skip_wrt_protect: WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ + + return QLA_SUCCESS; +} + +static int +qla24xx_erase_sector(scsi_qla_host_t *vha, uint32_t fdata) +{ + struct qla_hw_data *ha = vha->hw; + uint32_t start, finish; + + if (ha->flags.fac_supported) { + start = fdata >> 2; + finish = start + (ha->fdt_block_size >> 2) - 1; + return qla81xx_fac_erase_sector(vha, flash_data_addr(ha, + start), flash_data_addr(ha, finish)); + } + + return qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd, + (fdata & 0xff00) | ((fdata << 16) & 0xff0000) | + ((fdata >> 16) & 0xff)); } static int @@ -987,8 +1017,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, void *optrom = NULL; struct qla_hw_data *ha = vha->hw; - ret = QLA_SUCCESS; - /* Prepare burst-capable write on supported ISPs. */ if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && !(faddr & 0xfff) && dwords > OPTROM_BURST_DWORDS) { @@ -1004,7 +1032,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, rest_addr = (ha->fdt_block_size >> 2) - 1; sec_mask = ~rest_addr; - qla24xx_unprotect_flash(ha); + ret = qla24xx_unprotect_flash(vha); + if (ret != QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Unable to unprotect flash for update.\n"); + goto done; + } for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { fdata = (faddr & sec_mask) << 2; @@ -1017,9 +1050,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, ha->fdt_unprotect_sec_cmd, (fdata & 0xff00) | ((fdata << 16) & 0xff0000) | ((fdata >> 16) & 0xff)); - ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd, - (fdata & 0xff00) |((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); + ret = qla24xx_erase_sector(vha, fdata); if (ret != QLA_SUCCESS) { DEBUG9(qla_printk("Unable to erase sector: " "address=%x.\n", faddr)); @@ -1073,8 +1104,11 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, 0xff0000) | ((fdata >> 16) & 0xff)); } - qla24xx_protect_flash(ha); - + ret = qla24xx_protect_flash(vha); + if (ret != QLA_SUCCESS) + qla_printk(KERN_WARNING, ha, + "Unable to protect flash after update.\n"); +done: if (optrom) dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom, optrom_dma); |