diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 1612f9200a52..0f2a9f5d801c 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -91,18 +91,20 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, | |||
91 | { | 91 | { |
92 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 92 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
93 | struct device, kobj))); | 93 | struct device, kobj))); |
94 | unsigned long flags; | 94 | int size = ha->nvram_size; |
95 | char *nvram_cache = ha->nvram; | ||
95 | 96 | ||
96 | if (!capable(CAP_SYS_ADMIN) || off != 0) | 97 | if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) |
97 | return 0; | 98 | return 0; |
99 | if (off + count > size) { | ||
100 | size -= off; | ||
101 | count = size; | ||
102 | } | ||
98 | 103 | ||
99 | /* Read NVRAM. */ | 104 | /* Read NVRAM data from cache. */ |
100 | spin_lock_irqsave(&ha->hardware_lock, flags); | 105 | memcpy(buf, &nvram_cache[off], count); |
101 | ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->nvram_base, | ||
102 | ha->nvram_size); | ||
103 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
104 | 106 | ||
105 | return ha->nvram_size; | 107 | return count; |
106 | } | 108 | } |
107 | 109 | ||
108 | static ssize_t | 110 | static ssize_t |
@@ -144,6 +146,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, | |||
144 | /* Write NVRAM. */ | 146 | /* Write NVRAM. */ |
145 | spin_lock_irqsave(&ha->hardware_lock, flags); | 147 | spin_lock_irqsave(&ha->hardware_lock, flags); |
146 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); | 148 | 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, | ||
150 | count); | ||
147 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 151 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
148 | 152 | ||
149 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 153 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
@@ -298,18 +302,20 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, | |||
298 | { | 302 | { |
299 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 303 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
300 | struct device, kobj))); | 304 | struct device, kobj))); |
301 | unsigned long flags; | 305 | int size = ha->vpd_size; |
306 | char *vpd_cache = ha->vpd; | ||
302 | 307 | ||
303 | if (!capable(CAP_SYS_ADMIN) || off != 0) | 308 | if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) |
304 | return 0; | 309 | return 0; |
310 | if (off + count > size) { | ||
311 | size -= off; | ||
312 | count = size; | ||
313 | } | ||
305 | 314 | ||
306 | /* Read NVRAM. */ | 315 | /* Read NVRAM data from cache. */ |
307 | spin_lock_irqsave(&ha->hardware_lock, flags); | 316 | memcpy(buf, &vpd_cache[off], count); |
308 | ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->vpd_base, | ||
309 | ha->vpd_size); | ||
310 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
311 | 317 | ||
312 | return ha->vpd_size; | 318 | return count; |
313 | } | 319 | } |
314 | 320 | ||
315 | static ssize_t | 321 | static ssize_t |
@@ -327,6 +333,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, | |||
327 | /* Write NVRAM. */ | 333 | /* Write NVRAM. */ |
328 | spin_lock_irqsave(&ha->hardware_lock, flags); | 334 | spin_lock_irqsave(&ha->hardware_lock, flags); |
329 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); | 335 | ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); |
336 | ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); | ||
330 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 337 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
331 | 338 | ||
332 | return count; | 339 | return count; |