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

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

[SCSI] qla2xxx: Add Flash-Access-Control support for recent ISPs.



Given the low-level interface varies from one flash-part
manufacturer to the next, the Flash-Access-Control (FAC) mailbox
command makes the specific flash type transparent to the driver
by encapsulating a basic set of accessor and update routines.
Use these new routines where applicable by querying FAC opcode
get-sector-size at init-time.

Additional cleanups and
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent b9978769
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2260,7 +2260,7 @@ struct qla_hw_data {
		uint32_t	vsan_enabled		:1;
		uint32_t	npiv_supported		:1;
		uint32_t	fce_enabled		:1;
		uint32_t	hw_event_marker_found:1;
		uint32_t	fac_supported		:1;
	} flags;

	/* This spinlock is used to protect "io transactions", you must
@@ -2382,6 +2382,7 @@ struct qla_hw_data {
				IS_QLA25XX(ha) || IS_QLA81XX(ha))
#define IS_NOPOLLING_TYPE(ha)	((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
				(ha)->flags.msix_enabled)
#define IS_FAC_REQUIRED(ha)	(IS_QLA81XX(ha))

#define IS_IIDMA_CAPABLE(ha)    ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha)     ((ha)->device_type & DT_FWI2)
+14 −0
Original line number Diff line number Diff line
@@ -1403,6 +1403,20 @@ struct access_chip_rsp_84xx {
#define MBA_IDC_TIME_EXT	0x8102

#define MBC_IDC_ACK		0x101
#define MBC_FLASH_ACCESS_CTRL	0x3e	/* Control flash access. */

/* Flash access control option field bit definitions */
#define FAC_OPT_FORCE_SEMAPHORE		BIT_15
#define FAC_OPT_REQUESTOR_ID		BIT_14
#define FAC_OPT_CMD_SUBCODE		0xff

/* Flash access control command subcodes */
#define FAC_OPT_CMD_WRITE_PROTECT	0x00
#define FAC_OPT_CMD_WRITE_ENABLE	0x01
#define FAC_OPT_CMD_ERASE_SECTOR	0x02
#define FAC_OPT_CMD_LOCK_SEMAPHORE	0x03
#define FAC_OPT_CMD_UNLOCK_SEMAPHORE	0x04
#define FAC_OPT_CMD_GET_SECTOR_SIZE	0x05

struct nvram_81xx {
	/* NVRAM header. */
+9 −0
Original line number Diff line number Diff line
@@ -269,6 +269,15 @@ extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);

extern int qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);

extern int
qla81xx_fac_get_sector_size(scsi_qla_host_t *, uint32_t *);

extern int
qla81xx_fac_do_write_enable(scsi_qla_host_t *, int);

extern int
qla81xx_fac_erase_sector(scsi_qla_host_t *, uint32_t, uint32_t);

/*
 * Global Function Prototypes in qla_isr.c source file.
 */
+15 −0
Original line number Diff line number Diff line
@@ -1032,6 +1032,21 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
		spin_unlock_irqrestore(&ha->hardware_lock, flags);
	}

	if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
		uint32_t size;

		rval = qla81xx_fac_get_sector_size(vha, &size);
		if (rval == QLA_SUCCESS) {
			ha->flags.fac_supported = 1;
			ha->fdt_block_size = size << 2;
		} else {
			qla_printk(KERN_ERR, ha,
			    "Unsupported FAC firmware (%d.%02d.%02d).\n",
			    ha->fw_major_version, ha->fw_minor_version,
			    ha->fw_subminor_version);
		}
	}

	if (rval) {
		DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",
		    vha->host_no));
+97 −0
Original line number Diff line number Diff line
@@ -3228,3 +3228,100 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)

	return rval;
}

int
qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
{
	int rval;
	mbx_cmd_t mc;
	mbx_cmd_t *mcp = &mc;

	if (!IS_QLA81XX(vha->hw))
		return QLA_FUNCTION_FAILED;

	DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));

	mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
	mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
	mcp->out_mb = MBX_1|MBX_0;
	mcp->in_mb = MBX_1|MBX_0;
	mcp->tov = MBX_TOV_SECONDS;
	mcp->flags = 0;
	rval = qla2x00_mailbox_command(vha, mcp);

	if (rval != QLA_SUCCESS) {
		DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
		    __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
	} else {
		DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
		*sector_size = mcp->mb[1];
	}

	return rval;
}

int
qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
{
	int rval;
	mbx_cmd_t mc;
	mbx_cmd_t *mcp = &mc;

	if (!IS_QLA81XX(vha->hw))
		return QLA_FUNCTION_FAILED;

	DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));

	mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
	mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
	    FAC_OPT_CMD_WRITE_PROTECT;
	mcp->out_mb = MBX_1|MBX_0;
	mcp->in_mb = MBX_1|MBX_0;
	mcp->tov = MBX_TOV_SECONDS;
	mcp->flags = 0;
	rval = qla2x00_mailbox_command(vha, mcp);

	if (rval != QLA_SUCCESS) {
		DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
		    __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
	} else {
		DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
	}

	return rval;
}

int
qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
{
	int rval;
	mbx_cmd_t mc;
	mbx_cmd_t *mcp = &mc;

	if (!IS_QLA81XX(vha->hw))
		return QLA_FUNCTION_FAILED;

	DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));

	mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
	mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
	mcp->mb[2] = LSW(start);
	mcp->mb[3] = MSW(start);
	mcp->mb[4] = LSW(finish);
	mcp->mb[5] = MSW(finish);
	mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
	mcp->in_mb = MBX_2|MBX_1|MBX_0;
	mcp->tov = MBX_TOV_SECONDS;
	mcp->flags = 0;
	rval = qla2x00_mailbox_command(vha, mcp);

	if (rval != QLA_SUCCESS) {
		DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
		    "mb[2]=%x.\n", __func__, vha->host_no, rval, mcp->mb[0],
		    mcp->mb[1], mcp->mb[2]));
	} else {
		DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
	}

	return rval;
}
Loading