[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:
parent
338c9161e4
commit
b7cc176c9e
@ -175,10 +175,10 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
|
|||||||
|
|
||||||
if (ha->optrom_state != QLA_SREADING)
|
if (ha->optrom_state != QLA_SREADING)
|
||||||
return 0;
|
return 0;
|
||||||
if (off > ha->optrom_size)
|
if (off > ha->optrom_region_size)
|
||||||
return 0;
|
return 0;
|
||||||
if (off + count > ha->optrom_size)
|
if (off + count > ha->optrom_region_size)
|
||||||
count = ha->optrom_size - off;
|
count = ha->optrom_region_size - off;
|
||||||
|
|
||||||
memcpy(buf, &ha->optrom_buffer[off], count);
|
memcpy(buf, &ha->optrom_buffer[off], count);
|
||||||
|
|
||||||
@ -195,10 +195,10 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj,
|
|||||||
|
|
||||||
if (ha->optrom_state != QLA_SWRITING)
|
if (ha->optrom_state != QLA_SWRITING)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (off > ha->optrom_size)
|
if (off > ha->optrom_region_size)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
if (off + count > ha->optrom_size)
|
if (off + count > ha->optrom_region_size)
|
||||||
count = ha->optrom_size - off;
|
count = ha->optrom_region_size - off;
|
||||||
|
|
||||||
memcpy(&ha->optrom_buffer[off], buf, count);
|
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 scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
|
||||||
struct device, kobj)));
|
struct device, kobj)));
|
||||||
int val;
|
uint32_t start = 0;
|
||||||
|
uint32_t size = ha->optrom_size;
|
||||||
|
int val, valid;
|
||||||
|
|
||||||
if (off)
|
if (off)
|
||||||
return 0;
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (val) {
|
switch (val) {
|
||||||
@ -237,6 +241,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
ha->optrom_state = QLA_SWAITING;
|
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);
|
vfree(ha->optrom_buffer);
|
||||||
ha->optrom_buffer = NULL;
|
ha->optrom_buffer = NULL;
|
||||||
break;
|
break;
|
||||||
@ -244,44 +253,107 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
|
|||||||
if (ha->optrom_state != QLA_SWAITING)
|
if (ha->optrom_state != QLA_SWAITING)
|
||||||
break;
|
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_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) {
|
if (ha->optrom_buffer == NULL) {
|
||||||
qla_printk(KERN_WARNING, ha,
|
qla_printk(KERN_WARNING, ha,
|
||||||
"Unable to allocate memory for optrom retrieval "
|
"Unable to allocate memory for optrom retrieval "
|
||||||
"(%x).\n", ha->optrom_size);
|
"(%x).\n", ha->optrom_region_size);
|
||||||
|
|
||||||
ha->optrom_state = QLA_SWAITING;
|
ha->optrom_state = QLA_SWAITING;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ha->optrom_buffer, 0, ha->optrom_size);
|
DEBUG2(qla_printk(KERN_INFO, ha,
|
||||||
ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0,
|
"Reading flash region -- 0x%x/0x%x.\n",
|
||||||
ha->optrom_size);
|
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;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (ha->optrom_state != QLA_SWAITING)
|
if (ha->optrom_state != QLA_SWAITING)
|
||||||
break;
|
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_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) {
|
if (ha->optrom_buffer == NULL) {
|
||||||
qla_printk(KERN_WARNING, ha,
|
qla_printk(KERN_WARNING, ha,
|
||||||
"Unable to allocate memory for optrom update "
|
"Unable to allocate memory for optrom update "
|
||||||
"(%x).\n", ha->optrom_size);
|
"(%x).\n", ha->optrom_region_size);
|
||||||
|
|
||||||
ha->optrom_state = QLA_SWAITING;
|
ha->optrom_state = QLA_SWAITING;
|
||||||
return count;
|
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;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (ha->optrom_state != QLA_SWRITING)
|
if (ha->optrom_state != QLA_SWRITING)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0,
|
DEBUG2(qla_printk(KERN_INFO, ha,
|
||||||
ha->optrom_size);
|
"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;
|
break;
|
||||||
|
default:
|
||||||
|
count = -EINVAL;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -2478,6 +2478,8 @@ typedef struct scsi_qla_host {
|
|||||||
#define QLA_SWAITING 0
|
#define QLA_SWAITING 0
|
||||||
#define QLA_SREADING 1
|
#define QLA_SREADING 1
|
||||||
#define QLA_SWRITING 2
|
#define QLA_SWRITING 2
|
||||||
|
uint32_t optrom_region_start;
|
||||||
|
uint32_t optrom_region_size;
|
||||||
|
|
||||||
/* PCI expansion ROM image information. */
|
/* PCI expansion ROM image information. */
|
||||||
#define ROM_CODE_TYPE_BIOS 0
|
#define ROM_CODE_TYPE_BIOS 0
|
||||||
|
@ -779,6 +779,8 @@ struct device_reg_24xx {
|
|||||||
#define FA_NVRAM_VPD_SIZE 0x200
|
#define FA_NVRAM_VPD_SIZE 0x200
|
||||||
#define FA_NVRAM_VPD0_ADDR 0x00
|
#define FA_NVRAM_VPD0_ADDR 0x00
|
||||||
#define FA_NVRAM_VPD1_ADDR 0x100
|
#define FA_NVRAM_VPD1_ADDR 0x100
|
||||||
|
|
||||||
|
#define FA_BOOT_CODE_ADDR 0x00000
|
||||||
/*
|
/*
|
||||||
* RISC code begins at offset 512KB
|
* RISC code begins at offset 512KB
|
||||||
* within flash. Consisting of two
|
* within flash. Consisting of two
|
||||||
|
@ -559,7 +559,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
|
|||||||
ret = QLA_SUCCESS;
|
ret = QLA_SUCCESS;
|
||||||
|
|
||||||
/* Prepare burst-capable write on supported ISPs. */
|
/* 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) {
|
dwords > OPTROM_BURST_DWORDS) {
|
||||||
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
|
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
|
||||||
&optrom_dma, GFP_KERNEL);
|
&optrom_dma, GFP_KERNEL);
|
||||||
@ -1824,7 +1824,7 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
|
|||||||
uint8_t *pbuf;
|
uint8_t *pbuf;
|
||||||
uint32_t faddr, left, burst;
|
uint32_t faddr, left, burst;
|
||||||
|
|
||||||
if (offset & ~OPTROM_BURST_SIZE)
|
if (offset & 0xfff)
|
||||||
goto slow_read;
|
goto slow_read;
|
||||||
if (length < OPTROM_BURST_SIZE)
|
if (length < OPTROM_BURST_SIZE)
|
||||||
goto slow_read;
|
goto slow_read;
|
||||||
|
Loading…
Reference in New Issue
Block a user