[SCSI] qla2xxx: Allow region-based flash-part accesses.

Additional cleanups and
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Joe Carnuccio 2007-09-20 14:07:35 -07:00 committed by James Bottomley
parent 338c9161e4
commit b7cc176c9e
4 changed files with 96 additions and 20 deletions

View File

@ -175,10 +175,10 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
if (ha->optrom_state != QLA_SREADING)
return 0;
if (off > ha->optrom_size)
if (off > ha->optrom_region_size)
return 0;
if (off + count > ha->optrom_size)
count = ha->optrom_size - off;
if (off + count > ha->optrom_region_size)
count = ha->optrom_region_size - off;
memcpy(buf, &ha->optrom_buffer[off], count);
@ -195,10 +195,10 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj,
if (ha->optrom_state != QLA_SWRITING)
return -EINVAL;
if (off > ha->optrom_size)
if (off > ha->optrom_region_size)
return -ERANGE;
if (off + count > ha->optrom_size)
count = ha->optrom_size - off;
if (off + count > ha->optrom_region_size)
count = ha->optrom_region_size - off;
memcpy(&ha->optrom_buffer[off], buf, count);
@ -222,12 +222,16 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
int val;
uint32_t start = 0;
uint32_t size = ha->optrom_size;
int val, valid;
if (off)
return 0;
if (sscanf(buf, "%d", &val) != 1)
if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1)
return -EINVAL;
if (start > ha->optrom_size)
return -EINVAL;
switch (val) {
@ -237,6 +241,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
break;
ha->optrom_state = QLA_SWAITING;
DEBUG2(qla_printk(KERN_INFO, ha,
"Freeing flash region allocation -- 0x%x bytes.\n",
ha->optrom_region_size));
vfree(ha->optrom_buffer);
ha->optrom_buffer = NULL;
break;
@ -244,44 +253,107 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
if (ha->optrom_state != QLA_SWAITING)
break;
if (start & 0xfff) {
qla_printk(KERN_WARNING, ha,
"Invalid start region 0x%x/0x%x.\n", start, size);
return -EINVAL;
}
ha->optrom_region_start = start;
ha->optrom_region_size = start + size > ha->optrom_size ?
ha->optrom_size - start : size;
ha->optrom_state = QLA_SREADING;
ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
if (ha->optrom_buffer == NULL) {
qla_printk(KERN_WARNING, ha,
"Unable to allocate memory for optrom retrieval "
"(%x).\n", ha->optrom_size);
"(%x).\n", ha->optrom_region_size);
ha->optrom_state = QLA_SWAITING;
return count;
}
memset(ha->optrom_buffer, 0, ha->optrom_size);
ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0,
ha->optrom_size);
DEBUG2(qla_printk(KERN_INFO, ha,
"Reading flash region -- 0x%x/0x%x.\n",
ha->optrom_region_start, ha->optrom_region_size));
memset(ha->optrom_buffer, 0, ha->optrom_region_size);
ha->isp_ops->read_optrom(ha, ha->optrom_buffer,
ha->optrom_region_start, ha->optrom_region_size);
break;
case 2:
if (ha->optrom_state != QLA_SWAITING)
break;
/*
* We need to be more restrictive on which FLASH regions are
* allowed to be updated via user-space. Regions accessible
* via this method include:
*
* ISP21xx/ISP22xx/ISP23xx type boards:
*
* 0x000000 -> 0x020000 -- Boot code.
*
* ISP2322/ISP24xx type boards:
*
* 0x000000 -> 0x07ffff -- Boot code.
* 0x080000 -> 0x0fffff -- Firmware.
*
* ISP25xx type boards:
*
* 0x000000 -> 0x07ffff -- Boot code.
* 0x080000 -> 0x0fffff -- Firmware.
* 0x120000 -> 0x12ffff -- VPD and HBA parameters.
*/
valid = 0;
if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
valid = 1;
else if (start == (FA_BOOT_CODE_ADDR*4) ||
start == (FA_RISC_CODE_ADDR*4))
valid = 1;
else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4))
valid = 1;
if (!valid) {
qla_printk(KERN_WARNING, ha,
"Invalid start region 0x%x/0x%x.\n", start, size);
return -EINVAL;
}
ha->optrom_region_start = start;
ha->optrom_region_size = start + size > ha->optrom_size ?
ha->optrom_size - start : size;
ha->optrom_state = QLA_SWRITING;
ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size);
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
if (ha->optrom_buffer == NULL) {
qla_printk(KERN_WARNING, ha,
"Unable to allocate memory for optrom update "
"(%x).\n", ha->optrom_size);
"(%x).\n", ha->optrom_region_size);
ha->optrom_state = QLA_SWAITING;
return count;
}
memset(ha->optrom_buffer, 0, ha->optrom_size);
DEBUG2(qla_printk(KERN_INFO, ha,
"Staging flash region write -- 0x%x/0x%x.\n",
ha->optrom_region_start, ha->optrom_region_size));
memset(ha->optrom_buffer, 0, ha->optrom_region_size);
break;
case 3:
if (ha->optrom_state != QLA_SWRITING)
break;
ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0,
ha->optrom_size);
DEBUG2(qla_printk(KERN_INFO, ha,
"Writing flash region -- 0x%x/0x%x.\n",
ha->optrom_region_start, ha->optrom_region_size));
ha->isp_ops->write_optrom(ha, ha->optrom_buffer,
ha->optrom_region_start, ha->optrom_region_size);
break;
default:
count = -EINVAL;
}
return count;
}

View File

@ -2478,6 +2478,8 @@ typedef struct scsi_qla_host {
#define QLA_SWAITING 0
#define QLA_SREADING 1
#define QLA_SWRITING 2
uint32_t optrom_region_start;
uint32_t optrom_region_size;
/* PCI expansion ROM image information. */
#define ROM_CODE_TYPE_BIOS 0

View File

@ -779,6 +779,8 @@ struct device_reg_24xx {
#define FA_NVRAM_VPD_SIZE 0x200
#define FA_NVRAM_VPD0_ADDR 0x00
#define FA_NVRAM_VPD1_ADDR 0x100
#define FA_BOOT_CODE_ADDR 0x00000
/*
* RISC code begins at offset 512KB
* within flash. Consisting of two

View File

@ -559,7 +559,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
ret = QLA_SUCCESS;
/* Prepare burst-capable write on supported ISPs. */
if (IS_QLA25XX(ha) && !(faddr & ~OPTROM_BURST_SIZE) &&
if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
dwords > OPTROM_BURST_DWORDS) {
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
&optrom_dma, GFP_KERNEL);
@ -1824,7 +1824,7 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
uint8_t *pbuf;
uint32_t faddr, left, burst;
if (offset & ~OPTROM_BURST_SIZE)
if (offset & 0xfff)
goto slow_read;
if (length < OPTROM_BURST_SIZE)
goto slow_read;