mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
[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
4 changed files with 96 additions and 20 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue