Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c96d8d0 authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley
Browse files

[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: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent a3a63d55
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -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;
}
+21 −2
Original line number Diff line number Diff line
@@ -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);
@@ -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