diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_sup.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 40b059fc198..ad2fa01bd23 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -7,6 +7,7 @@ #include "qla_def.h" #include <linux/delay.h> +#include <linux/vmalloc.h> #include <asm/uaccess.h> static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t); @@ -642,7 +643,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, } /* Go with burst-write. */ - if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) { + if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) { /* Copy data to DMA'ble buffer. */ for (miter = 0, s = optrom, d = dwptr; miter < OPTROM_BURST_DWORDS; miter++, s++, d++) @@ -656,7 +657,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, "Unable to burst-write optrom segment " "(%x/%x/%llx).\n", ret, flash_data_to_access_addr(faddr), - optrom_dma); + (unsigned long long)optrom_dma); qla_printk(KERN_WARNING, ha, "Reverting to slow-write.\n"); @@ -745,9 +746,11 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, int ret, stat; uint32_t i; uint16_t *wptr; + unsigned long flags; ret = QLA_SUCCESS; + spin_lock_irqsave(&ha->hardware_lock, flags); qla2x00_lock_nvram_access(ha); /* Disable NVRAM write-protection. */ @@ -764,6 +767,7 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, qla2x00_set_nvram_protection(ha, stat); qla2x00_unlock_nvram_access(ha); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return ret; } @@ -776,9 +780,11 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, uint32_t i; uint32_t *dwptr; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + unsigned long flags; ret = QLA_SUCCESS; + spin_lock_irqsave(&ha->hardware_lock, flags); /* Enable flash write. */ WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); @@ -812,6 +818,7 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); return ret; } @@ -836,8 +843,20 @@ int qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, uint32_t bytes) { - return qla24xx_write_flash_data(ha, (uint32_t *)buf, - FA_VPD_NVRAM_ADDR | naddr, bytes >> 2); +#define RMW_BUFFER_SIZE (64 * 1024) + uint8_t *dbuf; + + dbuf = vmalloc(RMW_BUFFER_SIZE); + if (!dbuf) + return QLA_MEMORY_ALLOC_FAILED; + ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, + RMW_BUFFER_SIZE); + memcpy(dbuf + (naddr << 2), buf, bytes); + ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, + RMW_BUFFER_SIZE); + vfree(dbuf); + + return QLA_SUCCESS; } static inline void @@ -1853,7 +1872,8 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, qla_printk(KERN_WARNING, ha, "Unable to burst-read optrom segment " "(%x/%x/%llx).\n", rval, - flash_data_to_access_addr(faddr), optrom_dma); + flash_data_to_access_addr(faddr), + (unsigned long long)optrom_dma); qla_printk(KERN_WARNING, ha, "Reverting to slow-read.\n"); |