Commit 281afe19 authored by Seokmann Ju's avatar Seokmann Ju Committed by James Bottomley

[SCSI] qla2xxx: fix to honor ignored parameters in sysfs attributes

This is a patch to fix 'segmentation fault' issue which was initiated
by Richard Lary <rlary@us.ibm.com>.  Thanks again Richard.

- on following sysfs attritute function, changes have made so that both
  count and offset input parameters are honored by the functions.
    = qla2x00_sysfs_read_nvram()
    = qla2x00_sysfs_read_vpd()
- made changes so that NVRAM data to be cached to minimize H/W accesses
  during agent querying of the driver's.
Signed-off-by: default avatarSeokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent c835e372
...@@ -91,18 +91,20 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, ...@@ -91,18 +91,20 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
{ {
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj))); struct device, kobj)));
unsigned long flags; int size = ha->nvram_size;
char *nvram_cache = ha->nvram;
if (!capable(CAP_SYS_ADMIN) || off != 0) if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
return 0; return 0;
if (off + count > size) {
size -= off;
count = size;
}
/* Read NVRAM. */ /* Read NVRAM data from cache. */
spin_lock_irqsave(&ha->hardware_lock, flags); memcpy(buf, &nvram_cache[off], count);
ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->nvram_base,
ha->nvram_size);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ha->nvram_size; return count;
} }
static ssize_t static ssize_t
...@@ -144,6 +146,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, ...@@ -144,6 +146,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
/* Write NVRAM. */ /* Write NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags); 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,
count);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
...@@ -298,18 +302,20 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, ...@@ -298,18 +302,20 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
{ {
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj))); struct device, kobj)));
unsigned long flags; int size = ha->vpd_size;
char *vpd_cache = ha->vpd;
if (!capable(CAP_SYS_ADMIN) || off != 0) if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
return 0; return 0;
if (off + count > size) {
size -= off;
count = size;
}
/* Read NVRAM. */ /* Read NVRAM data from cache. */
spin_lock_irqsave(&ha->hardware_lock, flags); memcpy(buf, &vpd_cache[off], count);
ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->vpd_base,
ha->vpd_size);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ha->vpd_size; return count;
} }
static ssize_t static ssize_t
...@@ -327,6 +333,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, ...@@ -327,6 +333,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
/* Write NVRAM. */ /* Write NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags); 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);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
return count; return count;
......
...@@ -2340,10 +2340,14 @@ typedef struct scsi_qla_host { ...@@ -2340,10 +2340,14 @@ typedef struct scsi_qla_host {
uint8_t serial2; uint8_t serial2;
/* NVRAM configuration data */ /* NVRAM configuration data */
#define MAX_NVRAM_SIZE 4096
#define VPD_OFFSET MAX_NVRAM_SIZE / 2
uint16_t nvram_size; uint16_t nvram_size;
uint16_t nvram_base; uint16_t nvram_base;
void *nvram;
uint16_t vpd_size; uint16_t vpd_size;
uint16_t vpd_base; uint16_t vpd_base;
void *vpd;
uint16_t loop_reset_delay; uint16_t loop_reset_delay;
uint8_t retry_count; uint8_t retry_count;
......
...@@ -1461,8 +1461,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ...@@ -1461,8 +1461,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
uint16_t cnt; uint16_t cnt;
uint8_t *dptr1, *dptr2; uint8_t *dptr1, *dptr2;
init_cb_t *icb = ha->init_cb; init_cb_t *icb = ha->init_cb;
nvram_t *nv = (nvram_t *)ha->request_ring; nvram_t *nv = ha->nvram;
uint8_t *ptr = (uint8_t *)ha->request_ring; uint8_t *ptr = ha->nvram;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
rval = QLA_SUCCESS; rval = QLA_SUCCESS;
...@@ -1480,8 +1480,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ...@@ -1480,8 +1480,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
chksum += *ptr++; chksum += *ptr++;
DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no));
DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
ha->nvram_size));
/* Bad NVRAM data, set defaults parameters. */ /* Bad NVRAM data, set defaults parameters. */
if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
...@@ -3500,7 +3499,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ...@@ -3500,7 +3499,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
rval = QLA_SUCCESS; rval = QLA_SUCCESS;
icb = (struct init_cb_24xx *)ha->init_cb; icb = (struct init_cb_24xx *)ha->init_cb;
nv = (struct nvram_24xx *)ha->request_ring; nv = ha->nvram;
/* Determine NVRAM starting address. */ /* Determine NVRAM starting address. */
ha->nvram_size = sizeof(struct nvram_24xx); ha->nvram_size = sizeof(struct nvram_24xx);
...@@ -3512,7 +3511,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ...@@ -3512,7 +3511,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
ha->vpd_base = FA_NVRAM_VPD1_ADDR; ha->vpd_base = FA_NVRAM_VPD1_ADDR;
} }
/* Get NVRAM data and calculate checksum. */ /* Get VPD data into cache */
ha->vpd = ha->nvram + VPD_OFFSET;
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd,
ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
/* Get NVRAM data into cache and calculate checksum. */
dptr = (uint32_t *)nv; dptr = (uint32_t *)nv;
ha->isp_ops->read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, ha->isp_ops->read_nvram(ha, (uint8_t *)dptr, ha->nvram_base,
ha->nvram_size); ha->nvram_size);
...@@ -3520,8 +3524,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ...@@ -3520,8 +3524,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
chksum += le32_to_cpu(*dptr++); chksum += le32_to_cpu(*dptr++);
DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no));
DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
ha->nvram_size));
/* Bad NVRAM data, set defaults parameters. */ /* Bad NVRAM data, set defaults parameters. */
if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment