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

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
......@@ -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);
}
......
......@@ -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;
}
......
......@@ -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
......@@ -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
......
......@@ -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;
......
......@@ -93,7 +93,6 @@ extern int qla2xxx_mctp_dump(scsi_qla_host_t *);
extern int
qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *);
extern int qla2x00_init_rings(scsi_qla_host_t *);
extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
int, int, bool);
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
......@@ -108,6 +107,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
int qla24xx_detect_sfp(scsi_qla_host_t *vha);
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
extern void qla28xx_get_aux_images(struct scsi_qla_host *,
struct active_regions *);
extern void qla27xx_get_active_image(struct scsi_qla_host *,
struct active_regions *);
void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *,
......
This diff is collapsed.
......@@ -862,20 +862,58 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
ha->flt_region_boot_sec = start;
break;
case FLT_REG_AUX_IMG_PRI_28XX:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
ha->flt_region_aux_img_status_pri = start;
break;
case FLT_REG_AUX_IMG_SEC_28XX:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
ha->flt_region_aux_img_status_sec = start;
break;
case FLT_REG_NVRAM_SEC_28XX_0:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
if (ha->port_no == 0)
ha->flt_region_nvram_sec = start;
break;
case FLT_REG_NVRAM_SEC_28XX_1:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
if (ha->port_no == 1)
ha->flt_region_nvram_sec = start;
break;
case FLT_REG_NVRAM_SEC_28XX_2:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
if (ha->port_no == 2)
ha->flt_region_nvram_sec = start;
break;
case FLT_REG_NVRAM_SEC_28XX_3:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
if (ha->port_no == 3)
ha->flt_region_nvram_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_0:
if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
case FLT_REG_VPD_SEC_28XX_0:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
ha->flt_region_vpd_nvram_sec = start;
if (ha->port_no == 0)
ha->flt_region_vpd_sec = start;
}
break;
case FLT_REG_VPD_SEC_27XX_1:
if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
case FLT_REG_VPD_SEC_28XX_1:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
if (ha->port_no == 1)
ha->flt_region_vpd_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_2:
if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
case FLT_REG_VPD_SEC_28XX_2:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
if (ha->port_no == 2)
ha->flt_region_vpd_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_3:
if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
case FLT_REG_VPD_SEC_28XX_3:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
if (ha->port_no == 3)
ha->flt_region_vpd_sec = start;
break;
}
......@@ -3020,6 +3058,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
int i;
struct qla_hw_data *ha = vha->hw;
uint32_t faddr = 0;
struct active_regions active_regions = { };
if (IS_P3P_TYPE(ha))
return ret;
......@@ -3033,9 +3072,12 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
pcihdr = ha->flt_region_boot << 2;
if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
qla27xx_get_active_image(vha, &active_regions);
if (active_regions.global == QLA27XX_SECONDARY_IMAGE) {
pcihdr = ha->flt_region_boot_sec << 2;
}
}
do {
/* Verify PCI expansion ROM header. */
......@@ -3108,9 +3150,10 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
/* Read firmware image information. */
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
faddr = ha->flt_region_fw;
if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
if (active_regions.global == QLA27XX_SECONDARY_IMAGE)
faddr = ha->flt_region_fw_sec;
}
qla24xx_read_flash_data(vha, dcode, faddr, 8);
if (qla24xx_risc_firmware_invalid(dcode)) {
......
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