Commit b7cc176c authored by Joe Carnuccio's avatar Joe Carnuccio Committed by James Bottomley

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

Additional cleanups and
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 338c9161
...@@ -175,10 +175,10 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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 { ...@@ -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, ...@@ -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, ...@@ -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;
......
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