mirror of
https://github.com/adulau/aha.git
synced 2025-01-04 07:03:38 +00:00
[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 <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
a3a63d55a4
commit
2c96d8d0c1
2 changed files with 21 additions and 8 deletions
|
@ -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 scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
|
||||||
struct device, kobj)));
|
struct device, kobj)));
|
||||||
unsigned long flags;
|
|
||||||
uint16_t cnt;
|
uint16_t cnt;
|
||||||
|
|
||||||
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
|
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
|
||||||
|
@ -144,11 +143,9 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write NVRAM. */
|
/* 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->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
|
||||||
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base,
|
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base,
|
||||||
count);
|
count);
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
|
||||||
|
|
||||||
set_bit(ISP_ABORT_NEEDED, &ha->dpc_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 scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
|
||||||
struct device, kobj)));
|
struct device, kobj)));
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
|
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Write NVRAM. */
|
/* 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->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
|
||||||
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, 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;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "qla_def.h"
|
#include "qla_def.h"
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t);
|
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;
|
int ret, stat;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint16_t *wptr;
|
uint16_t *wptr;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
ret = QLA_SUCCESS;
|
ret = QLA_SUCCESS;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
qla2x00_lock_nvram_access(ha);
|
qla2x00_lock_nvram_access(ha);
|
||||||
|
|
||||||
/* Disable NVRAM write-protection. */
|
/* 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_set_nvram_protection(ha, stat);
|
||||||
|
|
||||||
qla2x00_unlock_nvram_access(ha);
|
qla2x00_unlock_nvram_access(ha);
|
||||||
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
return ret;
|
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 i;
|
||||||
uint32_t *dwptr;
|
uint32_t *dwptr;
|
||||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
ret = QLA_SUCCESS;
|
ret = QLA_SUCCESS;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
/* Enable flash write. */
|
/* Enable flash write. */
|
||||||
WRT_REG_DWORD(®->ctrl_status,
|
WRT_REG_DWORD(®->ctrl_status,
|
||||||
RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE);
|
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,
|
WRT_REG_DWORD(®->ctrl_status,
|
||||||
RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
|
RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
|
||||||
RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
|
RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
|
||||||
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -836,8 +843,20 @@ int
|
||||||
qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
|
qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
|
||||||
uint32_t bytes)
|
uint32_t bytes)
|
||||||
{
|
{
|
||||||
return qla24xx_write_flash_data(ha, (uint32_t *)buf,
|
#define RMW_BUFFER_SIZE (64 * 1024)
|
||||||
FA_VPD_NVRAM_ADDR | naddr, bytes >> 2);
|
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
|
static inline void
|
||||||
|
|
Loading…
Reference in a new issue