diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2007-10-19 18:59:15 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-23 15:53:55 -0400 |
commit | 2c96d8d0c17978bbf5eb82314d488f46d4a51280 (patch) | |
tree | 7506cb5fb1f90adae103fd223574411d68f2a4fe /drivers/scsi | |
parent | a3a63d55a4eec418d845a91222ac53443f62717b (diff) |
[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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 6 | ||||
-rw-r--r-- | 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 05fa7796a559..2f0bd5abb9ac 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, | |||
114 | { | 114 | { |
115 | struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, | 115 | struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, |
116 | struct device, kobj))); | 116 | struct device, kobj))); |
117 | unsigned long flags; | ||
118 | uint16_t cnt; | 117 | uint16_t cnt; |
119 | 118 | ||
120 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) | 119 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) |
@@ -144,11 +143,9 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, | |||
144 | } | 143 | } |
145 | 144 | ||
146 | /* Write NVRAM. */ | 145 | /* Write NVRAM. */ |
147 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
148 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); | 146 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); |
149 | ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base, | 147 | ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base, |
150 | count); | 148 | count); |
151 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
152 | 149 | ||
153 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 150 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
154 | 151 | ||
@@ -397,16 +394,13 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, | |||
397 | { | 394 | { |
398 | struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, | 395 | struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, |
399 | struct device, kobj))); | 396 | struct device, kobj))); |
400 | unsigned long flags; | ||
401 | 397 | ||
402 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) | 398 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) |
403 | return 0; | 399 | return 0; |
404 | 400 | ||
405 | /* Write NVRAM. */ | 401 | /* Write NVRAM. */ |
406 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
407 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); | 402 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); |
408 | ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); | 403 | ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); |
409 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
410 | 404 | ||
411 | return count; | 405 | return count; |
412 | } | 406 | } |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 6670ad585f28..c24f3d9dea76 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/vmalloc.h> | ||
10 | #include <asm/uaccess.h> | 11 | #include <asm/uaccess.h> |
11 | 12 | ||
12 | static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t); | 13 | 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, | |||
745 | int ret, stat; | 746 | int ret, stat; |
746 | uint32_t i; | 747 | uint32_t i; |
747 | uint16_t *wptr; | 748 | uint16_t *wptr; |
749 | unsigned long flags; | ||
748 | 750 | ||
749 | ret = QLA_SUCCESS; | 751 | ret = QLA_SUCCESS; |
750 | 752 | ||
753 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
751 | qla2x00_lock_nvram_access(ha); | 754 | qla2x00_lock_nvram_access(ha); |
752 | 755 | ||
753 | /* Disable NVRAM write-protection. */ | 756 | /* Disable NVRAM write-protection. */ |
@@ -764,6 +767,7 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
764 | qla2x00_set_nvram_protection(ha, stat); | 767 | qla2x00_set_nvram_protection(ha, stat); |
765 | 768 | ||
766 | qla2x00_unlock_nvram_access(ha); | 769 | qla2x00_unlock_nvram_access(ha); |
770 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
767 | 771 | ||
768 | return ret; | 772 | return ret; |
769 | } | 773 | } |
@@ -776,9 +780,11 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
776 | uint32_t i; | 780 | uint32_t i; |
777 | uint32_t *dwptr; | 781 | uint32_t *dwptr; |
778 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 782 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
783 | unsigned long flags; | ||
779 | 784 | ||
780 | ret = QLA_SUCCESS; | 785 | ret = QLA_SUCCESS; |
781 | 786 | ||
787 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
782 | /* Enable flash write. */ | 788 | /* Enable flash write. */ |
783 | WRT_REG_DWORD(®->ctrl_status, | 789 | WRT_REG_DWORD(®->ctrl_status, |
784 | RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); | 790 | 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, | |||
812 | WRT_REG_DWORD(®->ctrl_status, | 818 | WRT_REG_DWORD(®->ctrl_status, |
813 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); | 819 | RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); |
814 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ | 820 | RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ |
821 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
815 | 822 | ||
816 | return ret; | 823 | return ret; |
817 | } | 824 | } |
@@ -836,8 +843,20 @@ int | |||
836 | qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | 843 | qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, |
837 | uint32_t bytes) | 844 | uint32_t bytes) |
838 | { | 845 | { |
839 | return qla24xx_write_flash_data(ha, (uint32_t *)buf, | 846 | #define RMW_BUFFER_SIZE (64 * 1024) |
840 | FA_VPD_NVRAM_ADDR | naddr, bytes >> 2); | 847 | uint8_t *dbuf; |
848 | |||
849 | dbuf = vmalloc(RMW_BUFFER_SIZE); | ||
850 | if (!dbuf) | ||
851 | return QLA_MEMORY_ALLOC_FAILED; | ||
852 | ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | ||
853 | RMW_BUFFER_SIZE); | ||
854 | memcpy(dbuf + (naddr << 2), buf, bytes); | ||
855 | ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | ||
856 | RMW_BUFFER_SIZE); | ||
857 | vfree(dbuf); | ||
858 | |||
859 | return QLA_SUCCESS; | ||
841 | } | 860 | } |
842 | 861 | ||
843 | static inline void | 862 | static inline void |