From 2c96d8d0c17978bbf5eb82314d488f46d4a51280 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:15 -0700 Subject: [PATCH] [SCSI] qla2xxx: Handle unaligned sector writes during NVRAM/VPD updates. Since both NVRAM and VPD regions of the flash reside on unaligned sector boundaries, during update, the driver must perform a read-modify-write operation to the composite NVRAM/VPD region. This affects ISP25xx type boards only. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 6 ------ drivers/scsi/qla2xxx/qla_sup.c | 23 +++++++++++++++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 05fa7796a5..2f0bd5abb9 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -114,7 +114,6 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, { struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; uint16_t cnt; if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) @@ -144,11 +143,9 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, } /* Write NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base, count); - spin_unlock_irqrestore(&ha->hardware_lock, flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); @@ -397,16 +394,13 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, { struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) return 0; /* Write NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); - spin_unlock_irqrestore(&ha->hardware_lock, flags); return count; } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 6670ad585f..c24f3d9dea 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -7,6 +7,7 @@ #include "qla_def.h" #include +#include #include static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t); @@ -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 -- 2.39.5