mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 15:34:48 +08:00
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: Joe Carnuccio <joe.carnuccio@cavium.com> Signed-off-by: Mike Hernandez <mhernandez@marvell.com> Signed-off-by: Himanshu Madhani <hmadhani@marvell.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
ce0366df54
commit
5fa8774c7f
drivers/scsi/qla2xxx
@ -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,9 +529,16 @@ 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)
|
||||
faddr = ha->flt_region_vpd_sec << 2;
|
||||
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)) {
|
||||
@ -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, ®ions, 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,22 +4119,28 @@ struct qla_hw_data {
|
||||
uint32_t fdt_protect_sec_cmd;
|
||||
uint32_t fdt_wrt_sts_reg_cmd;
|
||||
|
||||
uint32_t flt_region_flt;
|
||||
uint32_t flt_region_fdt;
|
||||
uint32_t flt_region_boot;
|
||||
uint32_t flt_region_boot_sec;
|
||||
uint32_t flt_region_fw;
|
||||
uint32_t flt_region_fw_sec;
|
||||
uint32_t flt_region_vpd_nvram;
|
||||
uint32_t flt_region_vpd;
|
||||
uint32_t flt_region_vpd_sec;
|
||||
uint32_t flt_region_nvram;
|
||||
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;
|
||||
struct {
|
||||
uint32_t flt_region_flt;
|
||||
uint32_t flt_region_fdt;
|
||||
uint32_t flt_region_boot;
|
||||
uint32_t flt_region_boot_sec;
|
||||
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 *,
|
||||
|
@ -7236,95 +7236,281 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
|
||||
static void
|
||||
qla27xx_print_image(struct scsi_qla_host *vha, char *name,
|
||||
struct qla27xx_image_status *image_status)
|
||||
{
|
||||
ql_dbg(ql_dbg_init, vha, 0x018b,
|
||||
"%s %s: mask=%#02x gen=%#04x ver=%u.%u map=%#01x sum=%#08x sig=%#08x\n",
|
||||
name, "status",
|
||||
image_status->image_status_mask,
|
||||
le16_to_cpu(image_status->generation),
|
||||
image_status->ver_major,
|
||||
image_status->ver_minor,
|
||||
image_status->bitmap,
|
||||
le32_to_cpu(image_status->checksum),
|
||||
le32_to_cpu(image_status->signature));
|
||||
}
|
||||
|
||||
static bool
|
||||
qla28xx_check_aux_image_status_signature(
|
||||
struct qla27xx_image_status *image_status)
|
||||
{
|
||||
ulong signature = le32_to_cpu(image_status->signature);
|
||||
|
||||
return signature != QLA28XX_AUX_IMG_STATUS_SIGN;
|
||||
}
|
||||
|
||||
static bool
|
||||
qla27xx_check_image_status_signature(struct qla27xx_image_status *image_status)
|
||||
{
|
||||
ulong signature = le32_to_cpu(image_status->signature);
|
||||
|
||||
return
|
||||
signature != QLA27XX_IMG_STATUS_SIGN &&
|
||||
signature != QLA28XX_IMG_STATUS_SIGN;
|
||||
}
|
||||
|
||||
static ulong
|
||||
qla27xx_image_status_checksum(struct qla27xx_image_status *image_status)
|
||||
{
|
||||
uint32_t *p = (void *)image_status;
|
||||
uint n = sizeof(*image_status) / sizeof(*p);
|
||||
uint32_t sum = 0;
|
||||
|
||||
for ( ; n--; p++)
|
||||
sum += le32_to_cpup(p);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static inline uint
|
||||
qla28xx_component_bitmask(struct qla27xx_image_status *aux, uint bitmask)
|
||||
{
|
||||
return aux->bitmap & bitmask ?
|
||||
QLA27XX_SECONDARY_IMAGE : QLA27XX_PRIMARY_IMAGE;
|
||||
}
|
||||
|
||||
static void
|
||||
qla28xx_component_status(
|
||||
struct active_regions *active_regions, struct qla27xx_image_status *aux)
|
||||
{
|
||||
active_regions->aux.board_config =
|
||||
qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_BOARD_CONFIG);
|
||||
|
||||
active_regions->aux.vpd_nvram =
|
||||
qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_VPD_NVRAM);
|
||||
|
||||
active_regions->aux.npiv_config_0_1 =
|
||||
qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_0_1);
|
||||
|
||||
active_regions->aux.npiv_config_2_3 =
|
||||
qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_2_3);
|
||||
}
|
||||
|
||||
static int
|
||||
qla27xx_compare_image_generation(
|
||||
struct qla27xx_image_status *pri_image_status,
|
||||
struct qla27xx_image_status *sec_image_status)
|
||||
{
|
||||
/* calculate generation delta as uint16 (this accounts for wrap) */
|
||||
int16_t delta =
|
||||
le16_to_cpu(pri_image_status->generation) -
|
||||
le16_to_cpu(sec_image_status->generation);
|
||||
|
||||
ql_dbg(ql_dbg_init, NULL, 0x0180, "generation delta = %d\n", delta);
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
void
|
||||
qla28xx_get_aux_images(
|
||||
struct scsi_qla_host *vha, struct active_regions *active_regions)
|
||||
{
|
||||
struct qla27xx_image_status pri_image_status, sec_image_status;
|
||||
bool valid_pri_image = true, valid_sec_image = true;
|
||||
uint32_t *wptr;
|
||||
uint chksum, cnt, size = sizeof(pri_image_status) / sizeof(*wptr);
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint32_t signature;
|
||||
struct qla27xx_image_status pri_aux_image_status, sec_aux_image_status;
|
||||
bool valid_pri_image = false, valid_sec_image = false;
|
||||
bool active_pri_image = false, active_sec_image = false;
|
||||
|
||||
ha->active_image = 0;
|
||||
|
||||
if (!ha->flt_region_img_status_pri) {
|
||||
valid_pri_image = false;
|
||||
if (!ha->flt_region_aux_img_status_pri) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018a, "Primary aux image not addressed\n");
|
||||
goto check_sec_image;
|
||||
}
|
||||
|
||||
qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status),
|
||||
ha->flt_region_img_status_pri, size);
|
||||
qla24xx_read_flash_data(vha, (void *)&pri_aux_image_status,
|
||||
ha->flt_region_aux_img_status_pri,
|
||||
sizeof(pri_aux_image_status) >> 2);
|
||||
qla27xx_print_image(vha, "Primary aux image", &pri_aux_image_status);
|
||||
|
||||
signature = le32_to_cpu(pri_image_status.signature);
|
||||
if (signature != QLA27XX_IMG_STATUS_SIGN &&
|
||||
signature != QLA28XX_IMG_STATUS_SIGN) {
|
||||
if (qla28xx_check_aux_image_status_signature(&pri_aux_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018b,
|
||||
"Primary aux image signature (%#x) not valid\n",
|
||||
le32_to_cpu(pri_aux_image_status.signature));
|
||||
goto check_sec_image;
|
||||
}
|
||||
|
||||
if (qla27xx_image_status_checksum(&pri_aux_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018c,
|
||||
"Primary aux image checksum failed\n");
|
||||
goto check_sec_image;
|
||||
}
|
||||
|
||||
valid_pri_image = true;
|
||||
|
||||
if (pri_aux_image_status.image_status_mask & 1) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018d,
|
||||
"Primary aux image is active\n");
|
||||
active_pri_image = true;
|
||||
}
|
||||
|
||||
check_sec_image:
|
||||
if (!ha->flt_region_aux_img_status_sec) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018a,
|
||||
"Secondary aux image not addressed\n");
|
||||
goto check_valid_image;
|
||||
}
|
||||
|
||||
qla24xx_read_flash_data(vha, (void *)&sec_aux_image_status,
|
||||
ha->flt_region_aux_img_status_sec,
|
||||
sizeof(sec_aux_image_status) >> 2);
|
||||
qla27xx_print_image(vha, "Secondary aux image", &sec_aux_image_status);
|
||||
|
||||
if (qla28xx_check_aux_image_status_signature(&sec_aux_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018b,
|
||||
"Secondary aux image signature (%#x) not valid\n",
|
||||
le32_to_cpu(sec_aux_image_status.signature));
|
||||
goto check_valid_image;
|
||||
}
|
||||
|
||||
if (qla27xx_image_status_checksum(&sec_aux_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018c,
|
||||
"Secondary aux image checksum failed\n");
|
||||
goto check_valid_image;
|
||||
}
|
||||
|
||||
valid_sec_image = true;
|
||||
|
||||
if (sec_aux_image_status.image_status_mask & 1) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018d,
|
||||
"Secondary aux image is active\n");
|
||||
active_sec_image = true;
|
||||
}
|
||||
|
||||
check_valid_image:
|
||||
if (valid_pri_image && active_pri_image &&
|
||||
valid_sec_image && active_sec_image) {
|
||||
if (qla27xx_compare_image_generation(&pri_aux_image_status,
|
||||
&sec_aux_image_status) >= 0) {
|
||||
qla28xx_component_status(active_regions,
|
||||
&pri_aux_image_status);
|
||||
} else {
|
||||
qla28xx_component_status(active_regions,
|
||||
&sec_aux_image_status);
|
||||
}
|
||||
} else if (valid_pri_image && active_pri_image) {
|
||||
qla28xx_component_status(active_regions, &pri_aux_image_status);
|
||||
} else if (valid_sec_image && active_sec_image) {
|
||||
qla28xx_component_status(active_regions, &sec_aux_image_status);
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_init, vha, 0x018f,
|
||||
"aux images active: BCFG=%u VPD/NVR=%u NPIV0/1=%u NPIV2/3=%u\n",
|
||||
active_regions->aux.board_config,
|
||||
active_regions->aux.vpd_nvram,
|
||||
active_regions->aux.npiv_config_0_1,
|
||||
active_regions->aux.npiv_config_2_3);
|
||||
}
|
||||
|
||||
void
|
||||
qla27xx_get_active_image(struct scsi_qla_host *vha,
|
||||
struct active_regions *active_regions)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct qla27xx_image_status pri_image_status, sec_image_status;
|
||||
bool valid_pri_image = false, valid_sec_image = false;
|
||||
bool active_pri_image = false, active_sec_image = false;
|
||||
|
||||
if (!ha->flt_region_img_status_pri) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018a, "Primary image not addressed\n");
|
||||
goto check_sec_image;
|
||||
}
|
||||
|
||||
qla24xx_read_flash_data(vha, (void *)(&pri_image_status),
|
||||
ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2);
|
||||
qla27xx_print_image(vha, "Primary image", &pri_image_status);
|
||||
|
||||
if (qla27xx_check_image_status_signature(&pri_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018b,
|
||||
"Primary image signature (%#x) not valid\n",
|
||||
le32_to_cpu(pri_image_status.signature));
|
||||
valid_pri_image = false;
|
||||
goto check_sec_image;
|
||||
}
|
||||
|
||||
wptr = (uint32_t *)(&pri_image_status);
|
||||
cnt = size;
|
||||
|
||||
for (chksum = 0; cnt--; wptr++)
|
||||
chksum += le32_to_cpu(*wptr);
|
||||
|
||||
if (chksum) {
|
||||
if (qla27xx_image_status_checksum(&pri_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018c,
|
||||
"Primary image checksum failed (%#x)\n", chksum);
|
||||
valid_pri_image = false;
|
||||
"Primary image checksum failed\n");
|
||||
goto check_sec_image;
|
||||
}
|
||||
|
||||
valid_pri_image = true;
|
||||
|
||||
if (pri_image_status.image_status_mask & 1) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018d,
|
||||
"Primary image is active\n");
|
||||
active_pri_image = true;
|
||||
}
|
||||
|
||||
check_sec_image:
|
||||
if (!ha->flt_region_img_status_sec) {
|
||||
valid_sec_image = false;
|
||||
ql_dbg(ql_dbg_init, vha, 0x018a, "Secondary image not addressed\n");
|
||||
goto check_valid_image;
|
||||
}
|
||||
|
||||
qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status),
|
||||
ha->flt_region_img_status_sec, size);
|
||||
ha->flt_region_img_status_sec, sizeof(sec_image_status) >> 2);
|
||||
qla27xx_print_image(vha, "Secondary image", &sec_image_status);
|
||||
|
||||
signature = le32_to_cpu(sec_image_status.signature);
|
||||
if (signature != QLA27XX_IMG_STATUS_SIGN &&
|
||||
signature != QLA28XX_IMG_STATUS_SIGN) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018d,
|
||||
if (qla27xx_check_image_status_signature(&sec_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018b,
|
||||
"Secondary image signature (%#x) not valid\n",
|
||||
le32_to_cpu(sec_image_status.signature));
|
||||
valid_sec_image = false;
|
||||
goto check_valid_image;
|
||||
}
|
||||
|
||||
wptr = (uint32_t *)(&sec_image_status);
|
||||
cnt = size;
|
||||
for (chksum = 0; cnt--; wptr++)
|
||||
chksum += le32_to_cpu(*wptr);
|
||||
if (chksum) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018e,
|
||||
"Secondary image checksum failed (%#x)\n", chksum);
|
||||
valid_sec_image = false;
|
||||
if (qla27xx_image_status_checksum(&sec_image_status)) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018c,
|
||||
"Secondary image checksum failed\n");
|
||||
goto check_valid_image;
|
||||
}
|
||||
|
||||
valid_sec_image = true;
|
||||
|
||||
if (sec_image_status.image_status_mask & 1) {
|
||||
ql_dbg(ql_dbg_init, vha, 0x018d,
|
||||
"Secondary image is active\n");
|
||||
active_sec_image = true;
|
||||
}
|
||||
|
||||
check_valid_image:
|
||||
if (valid_pri_image && (pri_image_status.image_status_mask & 1))
|
||||
ha->active_image = QLA27XX_PRIMARY_IMAGE;
|
||||
if (valid_pri_image && active_pri_image)
|
||||
active_regions->global = QLA27XX_PRIMARY_IMAGE;
|
||||
|
||||
if (valid_sec_image && (sec_image_status.image_status_mask & 1)) {
|
||||
if (!ha->active_image ||
|
||||
le16_to_cpu(pri_image_status.generation) <
|
||||
le16_to_cpu(sec_image_status.generation)) {
|
||||
ha->active_image = QLA27XX_SECONDARY_IMAGE;
|
||||
if (valid_sec_image && active_sec_image) {
|
||||
if (!active_regions->global ||
|
||||
qla27xx_compare_image_generation(
|
||||
&pri_image_status, &sec_image_status) < 0) {
|
||||
active_regions->global = QLA27XX_SECONDARY_IMAGE;
|
||||
}
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x018f, "%s image\n",
|
||||
ha->active_image == 0 ? "default bootld and fw" :
|
||||
ha->active_image == 1 ? "primary" :
|
||||
ha->active_image == 2 ? "secondary" :
|
||||
"Invalid");
|
||||
|
||||
return ha->active_image;
|
||||
ql_dbg(ql_dbg_init, vha, 0x018f, "active image %s (%u)\n",
|
||||
active_regions->global == QLA27XX_DEFAULT_IMAGE ?
|
||||
"default (boot/fw)" :
|
||||
active_regions->global == QLA27XX_PRIMARY_IMAGE ?
|
||||
"primary" :
|
||||
active_regions->global == QLA27XX_SECONDARY_IMAGE ?
|
||||
"secondary" : "invalid",
|
||||
active_regions->global);
|
||||
}
|
||||
|
||||
bool qla24xx_risc_firmware_invalid(uint32_t *dword)
|
||||
@ -7714,7 +7900,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
|
||||
|
||||
dcode = fwdt->template;
|
||||
for (i = 0; i < risc_size; i++)
|
||||
dcode[i] = le32_to_cpu(fwcode[i]);
|
||||
dcode[i] = fwcode[i];
|
||||
|
||||
if (!qla27xx_fwdt_template_valid(dcode)) {
|
||||
ql_log(ql_log_warn, vha, 0x0175,
|
||||
@ -7777,6 +7963,7 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
|
||||
{
|
||||
int rval;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct active_regions active_regions = { };
|
||||
|
||||
if (ql2xfwloadbin == 2)
|
||||
goto try_blob_fw;
|
||||
@ -7787,10 +7974,12 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
|
||||
* 3) Golden-Firmware residing in flash -- (limited operation).
|
||||
*/
|
||||
|
||||
if (!IS_QLA27XX(ha) || !IS_QLA28XX(ha))
|
||||
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
|
||||
goto try_primary_fw;
|
||||
|
||||
if (qla27xx_find_valid_image(vha) != QLA27XX_SECONDARY_IMAGE)
|
||||
qla27xx_get_active_image(vha, &active_regions);
|
||||
|
||||
if (active_regions.global != QLA27XX_SECONDARY_IMAGE)
|
||||
goto try_primary_fw;
|
||||
|
||||
ql_dbg(ql_dbg_init, vha, 0x008b,
|
||||
@ -7986,6 +8175,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
|
||||
uint32_t chksum;
|
||||
uint16_t cnt;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint32_t faddr;
|
||||
struct active_regions active_regions = { };
|
||||
|
||||
rval = QLA_SUCCESS;
|
||||
icb = (struct init_cb_81xx *)ha->init_cb;
|
||||
@ -7997,14 +8188,35 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
|
||||
if (IS_P3P_TYPE(ha) || IS_QLA8031(ha))
|
||||
ha->vpd_size = FA_VPD_SIZE_82XX;
|
||||
|
||||
if (IS_QLA28XX(ha))
|
||||
qla28xx_get_aux_images(vha, &active_regions);
|
||||
|
||||
/* Get VPD data into cache */
|
||||
ha->vpd = ha->nvram + VPD_OFFSET;
|
||||
ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
|
||||
ha->vpd_size);
|
||||
|
||||
faddr = ha->flt_region_vpd;
|
||||
if (IS_QLA28XX(ha)) {
|
||||
if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
|
||||
faddr = ha->flt_region_vpd_sec;
|
||||
ql_dbg(ql_dbg_init, vha, 0x0110,
|
||||
"Loading %s nvram image.\n",
|
||||
active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
|
||||
"primary" : "secondary");
|
||||
}
|
||||
qla24xx_read_flash_data(vha, ha->vpd, faddr, ha->vpd_size >> 2);
|
||||
|
||||
/* Get NVRAM data into cache and calculate checksum. */
|
||||
ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
|
||||
ha->nvram_size);
|
||||
faddr = ha->flt_region_nvram;
|
||||
if (IS_QLA28XX(ha)) {
|
||||
if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
|
||||
faddr = ha->flt_region_nvram_sec;
|
||||
}
|
||||
ql_dbg(ql_dbg_init, vha, 0x0110,
|
||||
"Loading %s nvram image.\n",
|
||||
active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
|
||||
"primary" : "secondary");
|
||||
qla24xx_read_flash_data(vha, ha->nvram, faddr, ha->nvram_size >> 2);
|
||||
|
||||
dptr = (uint32_t *)nv;
|
||||
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
|
||||
chksum += le32_to_cpu(*dptr);
|
||||
|
@ -862,21 +862,59 @@ 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))
|
||||
ha->flt_region_vpd_sec = start;
|
||||
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))
|
||||
ha->flt_region_vpd_sec = start;
|
||||
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))
|
||||
ha->flt_region_vpd_sec = start;
|
||||
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))
|
||||
ha->flt_region_vpd_sec = start;
|
||||
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)
|
||||
pcihdr = ha->flt_region_boot_sec << 2;
|
||||
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)
|
||||
faddr = ha->flt_region_fw_sec;
|
||||
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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user