Commit 5fa8774c authored by Joe Carnuccio's avatar Joe Carnuccio Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Add 28xx flash primary/secondary status/image mechanism



Includes the following:
- correction to 27xx image status struct;
- factoring of 27xx image status validating routines to make common;
- image status generation compare that works across zero wrap;
- bsg interface to report current active images (as loaded by driver).

Signed-off-by: default avatarJoe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: default avatarMike Hernandez <mhernandez@marvell.com>
Signed-off-by: default avatarHimanshu Madhani <hmadhani@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent ce0366df
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -154,6 +154,8 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
	struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
	    struct device, kobj)));
	struct qla_hw_data *ha = vha->hw;
	uint32_t faddr;
	struct active_regions active_regions = { };

	if (!capable(CAP_SYS_ADMIN))
		return 0;
@@ -164,11 +166,21 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
		return -EAGAIN;
	}

	if (IS_NOCACHE_VPD_TYPE(ha))
		ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
		    ha->nvram_size);
	if (!IS_NOCACHE_VPD_TYPE(ha)) {
		mutex_unlock(&ha->optrom_mutex);
		goto skip;
	}

	faddr = ha->flt_region_nvram;
	if (IS_QLA28XX(ha)) {
		if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
			faddr = ha->flt_region_nvram_sec;
	}
	ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size);

	mutex_unlock(&ha->optrom_mutex);

skip:
	return memory_read_from_buffer(buf, count, &off, ha->nvram,
					ha->nvram_size);
}
@@ -504,6 +516,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
	    struct device, kobj)));
	struct qla_hw_data *ha = vha->hw;
	uint32_t faddr;
	struct active_regions active_regions = { };

	if (unlikely(pci_channel_offline(ha->pdev)))
		return -EAGAIN;
@@ -516,10 +529,17 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,

	faddr = ha->flt_region_vpd << 2;

	if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
	    qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
	if (IS_QLA28XX(ha)) {
		qla28xx_get_aux_images(vha, &active_regions);
		if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
			faddr = ha->flt_region_vpd_sec << 2;

		ql_dbg(ql_dbg_init, vha, 0x7070,
		    "Loading %s nvram image.\n",
		    active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
		    "primary" : "secondary");
	}

	mutex_lock(&ha->optrom_mutex);
	if (qla2x00_chip_is_down(vha)) {
		mutex_unlock(&ha->optrom_mutex);
@@ -528,6 +548,8 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,

	ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size);
	mutex_unlock(&ha->optrom_mutex);

	ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size);
skip:
	return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
}
+42 −0
Original line number Diff line number Diff line
@@ -2388,6 +2388,45 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
	return 0;
}

static int
qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
{
	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
	struct qla_hw_data *ha = vha->hw;
	struct qla_active_regions regions = { };
	struct active_regions active_regions = { };

	qla28xx_get_aux_images(vha, &active_regions);
	regions.global_image = active_regions.global;

	if (IS_QLA28XX(ha)) {
		qla27xx_get_active_image(vha, &active_regions);
		regions.board_config = active_regions.aux.board_config;
		regions.vpd_nvram = active_regions.aux.vpd_nvram;
		regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1;
		regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3;
	}

	ql_dbg(ql_dbg_user, vha, 0x70e1,
	    "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n",
	    __func__, vha->host_no, regions.global_image,
	    regions.board_config, regions.vpd_nvram,
	    regions.npiv_config_0_1, regions.npiv_config_2_3);

	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
	    bsg_job->reply_payload.sg_cnt, &regions, sizeof(regions));

	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
	bsg_reply->reply_payload_rcv_len = sizeof(regions);
	bsg_reply->result = DID_OK << 16;
	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
	bsg_job_done(bsg_job, bsg_reply->result,
	    bsg_reply->reply_payload_rcv_len);

	return 0;
}

static int
qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
{
@@ -2461,6 +2500,9 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
	case QL_VND_DPORT_DIAGNOSTICS:
		return qla2x00_do_dport_diagnostics(bsg_job);

	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
		return qla2x00_get_flash_image_status(bsg_job);

	default:
		return -ENOSYS;
	}
+11 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#define QL_VND_GET_PRIV_STATS	0x18
#define QL_VND_DPORT_DIAGNOSTICS	0x19
#define QL_VND_GET_PRIV_STATS_EX	0x1A
#define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E

/* BSG Vendor specific subcode returns */
#define EXT_STATUS_OK			0
@@ -279,4 +280,14 @@ struct qla_dport_diag {
#define QLA_DPORT_RESULT	0x0
#define QLA_DPORT_START		0x2

/* active images in flash */
struct qla_active_regions {
	uint8_t global_image;
	uint8_t board_config;
	uint8_t vpd_nvram;
	uint8_t npiv_config_0_1;
	uint8_t npiv_config_2_3;
	uint8_t reserved[32];
} __packed;

#endif
+45 −18
Original line number Diff line number Diff line
@@ -1204,6 +1204,9 @@ struct mbx_cmd_32 {
#define QLA27XX_IMG_STATUS_VER_MINOR    0x00
#define QLA27XX_IMG_STATUS_SIGN   0xFACEFADE
#define QLA28XX_IMG_STATUS_SIGN    0xFACEFADF
#define QLA28XX_IMG_STATUS_SIGN		0xFACEFADF
#define QLA28XX_AUX_IMG_STATUS_SIGN	0xFACEFAED
#define QLA27XX_DEFAULT_IMAGE		0
#define QLA27XX_PRIMARY_IMAGE  1
#define QLA27XX_SECONDARY_IMAGE    2

@@ -4116,6 +4119,7 @@ struct qla_hw_data {
	uint32_t	fdt_protect_sec_cmd;
	uint32_t	fdt_wrt_sts_reg_cmd;

	struct {
		uint32_t	flt_region_flt;
		uint32_t	flt_region_fdt;
		uint32_t	flt_region_boot;
@@ -4123,15 +4127,20 @@ struct qla_hw_data {
		uint32_t	flt_region_fw;
		uint32_t	flt_region_fw_sec;
		uint32_t	flt_region_vpd_nvram;
		uint32_t	flt_region_vpd_nvram_sec;
		uint32_t	flt_region_vpd;
		uint32_t	flt_region_vpd_sec;
		uint32_t	flt_region_nvram;
		uint32_t	flt_region_nvram_sec;
		uint32_t	flt_region_npiv_conf;
		uint32_t	flt_region_gold_fw;
		uint32_t	flt_region_fcp_prio;
		uint32_t	flt_region_bootload;
		uint32_t	flt_region_img_status_pri;
		uint32_t	flt_region_img_status_sec;
		uint32_t	flt_region_aux_img_status_pri;
		uint32_t	flt_region_aux_img_status_sec;
	};
	uint8_t         active_image;

	/* Needed for BEACON */
@@ -4252,9 +4261,20 @@ struct qla_hw_data {

	atomic_t zio_threshold;
	uint16_t last_zio_threshold;

#define DEFAULT_ZIO_THRESHOLD 5
};

struct active_regions {
	uint8_t global;
	struct {
		uint8_t board_config;
		uint8_t vpd_nvram;
		uint8_t npiv_config_0_1;
		uint8_t npiv_config_2_3;
	} aux;
};

#define FW_ABILITY_MAX_SPEED_MASK	0xFUL
#define FW_ABILITY_MAX_SPEED_16G	0x0
#define FW_ABILITY_MAX_SPEED_32G	0x1
@@ -4469,13 +4489,20 @@ typedef struct scsi_qla_host {
struct qla27xx_image_status {
	uint8_t image_status_mask;
	uint16_t generation;
	uint8_t reserved[3];
	uint8_t ver_minor;
	uint8_t ver_major;
	uint8_t ver_minor;
	uint8_t bitmap;		/* 28xx only */
	uint8_t reserved[2];
	uint32_t checksum;
	uint32_t signature;
} __packed;

/* 28xx aux image status bimap values */
#define QLA28XX_AUX_IMG_BOARD_CONFIG		BIT_0
#define QLA28XX_AUX_IMG_VPD_NVRAM		BIT_1
#define QLA28XX_AUX_IMG_NPIV_CONFIG_0_1		BIT_2
#define QLA28XX_AUX_IMG_NPIV_CONFIG_2_3		BIT_3

#define SET_VP_IDX	1
#define SET_AL_PA	2
#define RESET_VP_IDX	3
+12 −0
Original line number Diff line number Diff line
@@ -1515,6 +1515,18 @@ struct qla_flt_header {
#define FLT_REG_VPD_SEC_27XX_2	0xD8
#define FLT_REG_VPD_SEC_27XX_3	0xDA

/* 28xx */
#define FLT_REG_AUX_IMG_PRI_28XX	0x125
#define FLT_REG_AUX_IMG_SEC_28XX	0x126
#define FLT_REG_VPD_SEC_28XX_0		0x10C
#define FLT_REG_VPD_SEC_28XX_1		0x10E
#define FLT_REG_VPD_SEC_28XX_2		0x110
#define FLT_REG_VPD_SEC_28XX_3		0x112
#define FLT_REG_NVRAM_SEC_28XX_0	0x10D
#define FLT_REG_NVRAM_SEC_28XX_1	0x10F
#define FLT_REG_NVRAM_SEC_28XX_2	0x111
#define FLT_REG_NVRAM_SEC_28XX_3	0x113

struct qla_flt_region {
	uint16_t code;
	uint8_t attribute;
Loading