Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+90 −18
Original line number Original line Diff line number Diff line
@@ -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;
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
+2 −2
Original line number Original line Diff line number Diff line
@@ -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;