summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_sup.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_sup.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c30
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(&reg->ctrl_status,
RD_REG_DWORD(&reg->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(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->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");