diff --git a/qla2x00t-32gbit/Makefile b/qla2x00t-32gbit/Makefile index 9399cc155..c2cc64523 100644 --- a/qla2x00t-32gbit/Makefile +++ b/qla2x00t-32gbit/Makefile @@ -46,7 +46,7 @@ INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra ifneq ($(PATCHLEVEL),) ccflags-y += $(call cc-option,-Wextra) -Wno-unused-parameter \ - -Wno-missing-field-initializers -I$(src)/../scst/include\ + -Wno-missing-field-initializers -I$(src)/../scst/include -I$(src)\ -DDEFAULT_SYMBOL_NAMESPACE=QLA32GB ifneq ($(CONFIG_SCSI_QLA2XXX_TARGET),) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 97cabd7e0..3a5f6f275 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -26,7 +26,8 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, struct qla_hw_data *ha = vha->hw; int rval = 0; - if (!(ha->fw_dump_reading || ha->mctp_dump_reading)) + if (!(ha->fw_dump_reading || ha->mctp_dump_reading || + ha->mpi_fw_dump_reading)) return 0; mutex_lock(&ha->optrom_mutex); @@ -42,6 +43,10 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, } else if (ha->mctp_dumped && ha->mctp_dump_reading) { rval = memory_read_from_buffer(buf, count, &off, ha->mctp_dump, MCTP_DUMP_SIZE); + } else if (ha->mpi_fw_dumped && ha->mpi_fw_dump_reading) { + rval = memory_read_from_buffer(buf, count, &off, + ha->mpi_fw_dump, + ha->mpi_fw_dump_len); } else if (ha->fw_dump_reading) { rval = memory_read_from_buffer(buf, count, &off, ha->fw_dump, ha->fw_dump_len); @@ -103,7 +108,6 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj, qla82xx_set_reset_owner(vha); qla8044_idc_unlock(ha); } else { - ha->fw_dump_mpi = 1; qla2x00_system_error(vha); } break; @@ -137,6 +141,22 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj, vha->host_no); } break; + case 8: + if (!ha->mpi_fw_dump_reading) + break; + ql_log(ql_log_info, vha, 0x70e7, + "MPI firmware dump cleared on (%ld).\n", vha->host_no); + ha->mpi_fw_dump_reading = 0; + ha->mpi_fw_dumped = 0; + break; + case 9: + if (ha->mpi_fw_dumped && !ha->mpi_fw_dump_reading) { + ha->mpi_fw_dump_reading = 1; + ql_log(ql_log_info, vha, 0x70e8, + "Raw MPI firmware dump ready for read on (%ld).\n", + vha->host_no); + } + break; } return count; } @@ -706,7 +726,8 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, scsi_unblock_requests(vha->host); break; case 0x2025d: - if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return -EPERM; ql_log(ql_log_info, vha, 0x706f, @@ -724,6 +745,8 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP); qla83xx_idc_unlock(vha, 0); break; + } else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + qla27xx_reset_mpi(vha); } else { /* Make sure FC side is not in reset */ WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) != @@ -737,6 +760,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, scsi_unblock_requests(vha->host); break; } + break; case 0x2025e: if (!IS_P3P_TYPE(ha) || vha != base_vha) { ql_log(ql_log_info, vha, 0x7071, diff --git a/qla2x00t-32gbit/qla_dbg.c b/qla2x00t-32gbit/qla_dbg.c index 88a56e848..8b7d0e476 100644 --- a/qla2x00t-32gbit/qla_dbg.c +++ b/qla2x00t-32gbit/qla_dbg.c @@ -73,6 +73,8 @@ #include "qla_def.h" #include +#define CREATE_TRACE_POINTS +#include static uint32_t ql_dbg_offset = 0x800; @@ -776,16 +778,16 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) if (rval == QLA_SUCCESS) { dmp_reg = ®->flash_address; - for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->pbiu_reg); cnt++, dmp_reg++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); dmp_reg = ®->u.isp2300.req_q_in; - for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; + for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_host_reg); cnt++, dmp_reg++) fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); dmp_reg = ®->u.isp2300.mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; + for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, dmp_reg++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); @@ -797,7 +799,7 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) WRT_REG_WORD(®->ctrl_status, 0x00); dmp_reg = ®->risc_hw; - for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; + for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_hdw_reg); cnt++, dmp_reg++) fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); @@ -858,12 +860,12 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Get RISC SRAM. */ if (rval == QLA_SUCCESS) rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram, - sizeof(fw->risc_ram) / 2, &nxt); + ARRAY_SIZE(fw->risc_ram), &nxt); /* Get stack SRAM. */ if (rval == QLA_SUCCESS) rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram, - sizeof(fw->stack_ram) / 2, &nxt); + ARRAY_SIZE(fw->stack_ram), &nxt); /* Get data SRAM. */ if (rval == QLA_SUCCESS) @@ -942,7 +944,7 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) } if (rval == QLA_SUCCESS) { dmp_reg = ®->flash_address; - for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->pbiu_reg); cnt++, dmp_reg++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); dmp_reg = ®->u.isp2100.mailbox0; @@ -954,12 +956,12 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) } dmp_reg = ®->u.isp2100.unused_2[0]; - for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->dma_reg); cnt++, dmp_reg++) fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); WRT_REG_WORD(®->ctrl_status, 0x00); dmp_reg = ®->risc_hw; - for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_hdw_reg); cnt++, dmp_reg++) fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg)); WRT_REG_WORD(®->pcr, 0x2000); @@ -1039,7 +1041,7 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); } - for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS; + for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_ram) && rval == QLA_SUCCESS; cnt++, risc_address++) { WRT_MAILBOX_REG(ha, reg, 1, risc_address); WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT); @@ -1143,7 +1145,7 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Host interface registers. */ dmp_reg = ®->flash_addr; - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++) fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ @@ -1176,7 +1178,7 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Mailbox registers. */ mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ @@ -1419,7 +1421,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Host interface registers. */ dmp_reg = ®->flash_addr; - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++) fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ @@ -1468,7 +1470,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Mailbox registers. */ mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ @@ -1743,7 +1745,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Host interface registers. */ dmp_reg = ®->flash_addr; - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++) fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ @@ -1792,7 +1794,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Mailbox registers. */ mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ @@ -2091,7 +2093,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Host interface registers. */ dmp_reg = ®->flash_addr; - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++) fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg)); /* Disable interrupts. */ @@ -2140,7 +2142,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Mailbox registers. */ mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++) + for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg)); /* Transfer sequence registers. */ @@ -2537,15 +2539,30 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; - - if (!ql_mask_match(level)) - return; + char pbuf[64]; va_start(va, fmt); vaf.fmt = fmt; vaf.va = &va; + if (!ql_mask_match(level)) { + if (vha != NULL) { + const struct pci_dev *pdev = vha->hw->pdev; + /* : Message */ + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ", + QL_MSGHDR, dev_name(&(pdev->dev)), id, + vha->host_no); + } else { + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", + QL_MSGHDR, "0000:00:00.0", id); + } + pbuf[sizeof(pbuf) - 1] = 0; + trace_ql_dbg_log(pbuf, &vaf); + va_end(va); + return; + } + if (vha != NULL) { const struct pci_dev *pdev = vha->hw->pdev; /* : Message */ diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 8cc106a1a..b2f693944 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3250,6 +3250,7 @@ struct isp_operations { uint32_t); void (*fw_dump) (struct scsi_qla_host *, int); + void (*mpi_fw_dump)(struct scsi_qla_host *, int); int (*beacon_on) (struct scsi_qla_host *); int (*beacon_off) (struct scsi_qla_host *); @@ -3775,6 +3776,11 @@ struct qlt_hw_data { #define LEAK_EXCHG_THRESH_HOLD_PERCENT 75 /* 75 percent */ +struct qla_hw_data_stat { + u32 num_fw_dump; + u32 num_mpi_reset; +}; + /* * Qlogic host adapter specific data structure. */ @@ -4257,7 +4263,6 @@ struct qla_hw_data { uint32_t fw_dump_len; u32 fw_dump_alloc_len; bool fw_dumped; - bool fw_dump_mpi; unsigned long fw_dump_cap_flags; #define RISC_PAUSE_CMPL 0 #define DMA_SHUTDOWN_CMPL 1 @@ -4268,6 +4273,10 @@ struct qla_hw_data { #define ISP_MBX_RDY 6 #define ISP_SOFT_RESET_CMPL 7 int fw_dump_reading; + void *mpi_fw_dump; + u32 mpi_fw_dump_len; + unsigned int mpi_fw_dump_reading:1; + unsigned int mpi_fw_dumped:1; int prev_minidump_failed; dma_addr_t eft_dma; void *eft; @@ -4481,6 +4490,8 @@ struct qla_hw_data { uint16_t last_zio_threshold; #define DEFAULT_ZIO_THRESHOLD 5 + + struct qla_hw_data_stat stat; }; struct active_regions { diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 4b44e569b..63fce1374 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -177,6 +177,7 @@ extern int ql2xenablemsix; extern int qla2xuseresexchforels; extern int ql2xexlogins; extern int ql2xdifbundlinginternalbuffers; +extern int ql2xfulldump_on_mpifail; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); @@ -649,6 +650,7 @@ extern void qla82xx_fw_dump(scsi_qla_host_t *, int); extern void qla8044_fw_dump(scsi_qla_host_t *, int); extern void qla27xx_fwdump(scsi_qla_host_t *, int); +extern void qla27xx_mpi_fwdump(scsi_qla_host_t *, int); extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *, void *); extern int qla27xx_fwdt_template_valid(void *); extern ulong qla27xx_fwdt_template_size(void *); @@ -942,5 +944,6 @@ extern void qla24xx_process_purex_list(struct purex_list *); /* nvme.c */ void qla_nvme_unregister_remote_port(struct fc_port *fcport); +void qla27xx_reset_mpi(scsi_qla_host_t *vha); void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea); #endif /* _QLA_GBL_H */ diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 1d08c4b64..8061cb734 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -3339,6 +3339,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) dump_size / 1024); if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + ha->mpi_fw_dump = (char *)fw_dump + + ha->fwdt[1].dump_size; mutex_unlock(&ha->optrom_mutex); return; } @@ -5081,6 +5083,54 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) return (rval); } +static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha) +{ + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + fc_port_t *fcport; + int rval; + + if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { + /* borrowing */ + u32 *bp, sz; + + memset(ha->init_cb, 0, ha->init_cb_size); + sz = min_t(int, sizeof(struct els_plogi_payload), + ha->init_cb_size); + rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, + ha->init_cb, sz); + if (rval == QLA_SUCCESS) { + __be32 *q = &ha->plogi_els_payld.data[0]; + + bp = (uint32_t *)ha->init_cb; + cpu_to_be32_array(q, bp, sz / 4); + memcpy(bp, q, sizeof(ha->plogi_els_payld.data)); + } else { + ql_dbg(ql_dbg_init, vha, 0x00d1, + "PLOGI ELS param read fail.\n"); + goto skip_login; + } + } + + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (fcport->n2n_flag) { + qla24xx_fcport_handle_login(vha, fcport); + return QLA_SUCCESS; + } + } + +skip_login: + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_retry++; + spin_unlock_irqrestore(&vha->work_lock, flags); + + if (vha->scan.scan_retry < MAX_SCAN_RETRIES) { + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + } + return QLA_FUNCTION_FAILED; +} + /* * qla2x00_configure_local_loop * Updates Fibre Channel Device Database with local loop devices. @@ -5098,7 +5148,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) int found_devs; int found; fc_port_t *fcport, *new_fcport; - uint16_t index; uint16_t entries; struct gid_list_info *gid; @@ -5108,47 +5157,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) unsigned long flags; /* Inititae N2N login. */ - if (N2N_TOPO(ha)) { - if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { - /* borrowing */ - u32 *bp, sz; - - memset(ha->init_cb, 0, ha->init_cb_size); - sz = min_t(int, sizeof(struct els_plogi_payload), - ha->init_cb_size); - rval = qla24xx_get_port_login_templ(vha, - ha->init_cb_dma, (void *)ha->init_cb, sz); - if (rval == QLA_SUCCESS) { - __be32 *q = &ha->plogi_els_payld.data[0]; - - bp = (uint32_t *)ha->init_cb; - cpu_to_be32_array(q, bp, sz / 4); - - memcpy(bp, q, sizeof(ha->plogi_els_payld.data)); - } else { - ql_dbg(ql_dbg_init, vha, 0x00d1, - "PLOGI ELS param read fail.\n"); - goto skip_login; - } - } - - list_for_each_entry(fcport, &vha->vp_fcports, list) { - if (fcport->n2n_flag) { - qla24xx_fcport_handle_login(vha, fcport); - return QLA_SUCCESS; - } - } -skip_login: - spin_lock_irqsave(&vha->work_lock, flags); - vha->scan.scan_retry++; - spin_unlock_irqrestore(&vha->work_lock, flags); - - if (vha->scan.scan_retry < MAX_SCAN_RETRIES) { - set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - } - return QLA_FUNCTION_FAILED; - } + if (N2N_TOPO(ha)) + return qla2x00_configure_n2n_loop(vha); found_devs = 0; new_fcport = NULL; diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 865024863..37986c74c 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -769,6 +769,39 @@ qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id, return NULL; } +/* Shall be called only on supported adapters. */ +static void +qla27xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb) +{ + struct qla_hw_data *ha = vha->hw; + bool reset_isp_needed = 0; + + ql_log(ql_log_warn, vha, 0x02f0, + "MPI Heartbeat stop. MPI reset is%s needed. " + "MB0[%xh] MB1[%xh] MB2[%xh] MB3[%xh]\n", + mb[0] & BIT_8 ? "" : " not", + mb[0], mb[1], mb[2], mb[3]); + + if ((mb[1] & BIT_8) == 0) + return; + + ql_log(ql_log_warn, vha, 0x02f1, + "MPI Heartbeat stop. FW dump needed\n"); + + if (ql2xfulldump_on_mpifail) { + ha->isp_ops->fw_dump(vha, 1); + reset_isp_needed = 1; + } + + ha->isp_ops->mpi_fw_dump(vha, 1); + + if (reset_isp_needed) { + vha->hw->flags.fw_init_done = 0; + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + } +} + /** * qla2x00_async_event() - Process aynchronous events. * @vha: SCSI driver HA context @@ -884,9 +917,9 @@ skip_rio: "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n ", mb[1], mb[2], mb[3]); - ha->fw_dump_mpi = - (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && - RD_REG_WORD(®24->mailbox7) & BIT_8; + if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + RD_REG_WORD(®24->mailbox7) & BIT_8) + ha->isp_ops->mpi_fw_dump(vha, 1); ha->isp_ops->fw_dump(vha, 1); ha->flags.fw_init_done = 0; QLA_FW_STOPPED(ha); @@ -1387,20 +1420,7 @@ global_port_update: case MBA_IDC_AEN: if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - ha->flags.fw_init_done = 0; - ql_log(ql_log_warn, vha, 0xffff, - "MPI Heartbeat stop. Chip reset needed. MB0[%xh] MB1[%xh] MB2[%xh] MB3[%xh]\n", - mb[0], mb[1], mb[2], mb[3]); - - if ((mb[1] & BIT_8) || - (mb[2] & BIT_8)) { - ql_log(ql_log_warn, vha, 0xd013, - "MPI Heartbeat stop. FW dump needed\n"); - ha->fw_dump_mpi = 1; - ha->isp_ops->fw_dump(vha, 1); - } - set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); + qla27xx_handle_8200_aen(vha, mb); } else if (IS_QLA83XX(ha)) { mb[4] = RD_REG_WORD(®24->mailbox4); mb[5] = RD_REG_WORD(®24->mailbox5); diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 0937121db..41fc64a68 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -621,11 +621,12 @@ static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport) } static struct nvme_fc_port_template qla_nvme_fc_transport = { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0) +#if 0 /* * See also commit 863fbae929c7 ("nvme_fc: add module to ops template - * to allow module references"). + * to allow module references"). See also commit 8c5c66052920 + * ("nvme-fc: Revert "add module to ops template to allow module + * references"") # v5.7-rc1. */ .module = THIS_MODULE, #endif diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index a73c2fc4c..7772e7971 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -48,6 +48,11 @@ static int apidev_major; */ struct kmem_cache *srb_cachep; +int ql2xfulldump_on_mpifail; +module_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ql2xfulldump_on_mpifail, + "Set this to take full dump on MPI hang."); + /* * CT6 CTX allocation cache */ @@ -2564,6 +2569,7 @@ static struct isp_operations qla27xx_isp_ops = { .read_nvram = NULL, .write_nvram = NULL, .fw_dump = qla27xx_fwdump, + .mpi_fw_dump = qla27xx_mpi_fwdump, .beacon_on = qla24xx_beacon_on, .beacon_off = qla24xx_beacon_off, .beacon_blink = qla83xx_beacon_blink, @@ -3983,19 +3989,6 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport, set_bit(RELOGIN_NEEDED, &vha->dpc_flags); } -/* - * qla2x00_mark_all_devices_lost - * Updates fcport state when device goes offline. - * - * Input: - * ha = adapter block pointer. - * fcport = port structure pointer. - * - * Return: - * None. - * - * Context: - */ void qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha) { @@ -4007,16 +4000,6 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha) list_for_each_entry(fcport, &vha->vp_fcports, list) { fcport->scan_state = 0; qlt_schedule_sess_for_deletion(fcport); - - if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx) - continue; - - /* - * No point in marking the device as lost, if the device is - * already DEAD. - */ - if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) - continue; } } diff --git a/qla2x00t-32gbit/qla_tmpl.c b/qla2x00t-32gbit/qla_tmpl.c index 6aeb1c3fb..342363862 100644 --- a/qla2x00t-32gbit/qla_tmpl.c +++ b/qla2x00t-32gbit/qla_tmpl.c @@ -12,6 +12,33 @@ #define IOBASE(vha) IOBAR(ISPREG(vha)) #define INVALID_ENTRY ((struct qla27xx_fwdt_entry *)0xffffffffffffffffUL) +/* hardware_lock assumed held. */ +static void +qla27xx_write_remote_reg(struct scsi_qla_host *vha, + u32 addr, u32 data) +{ + char *reg = (char *)ISPREG(vha); + + ql_dbg(ql_dbg_misc, vha, 0xd300, + "%s: addr/data = %xh/%xh\n", __func__, addr, data); + + WRT_REG_DWORD(reg + IOBASE(vha), 0x40); + WRT_REG_DWORD(reg + 0xc4, data); + WRT_REG_DWORD(reg + 0xc0, addr); +} + +void +qla27xx_reset_mpi(scsi_qla_host_t *vha) +{ + ql_dbg(ql_dbg_misc + ql_dbg_verbose, vha, 0xd301, + "Entered %s.\n", __func__); + + qla27xx_write_remote_reg(vha, 0x104050, 0x40004); + qla27xx_write_remote_reg(vha, 0x10405c, 0x4); + + vha->hw->stat.num_mpi_reset++; +} + static inline void qla27xx_insert16(uint16_t value, void *buf, ulong *len) { @@ -997,6 +1024,62 @@ qla27xx_fwdt_template_valid(void *p) return true; } +void +qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked) +{ + ulong flags = 0; + bool need_mpi_reset = 1; + +#ifndef __CHECKER__ + if (!hardware_locked) + spin_lock_irqsave(&vha->hw->hardware_lock, flags); +#endif + if (!vha->hw->mpi_fw_dump) { + ql_log(ql_log_warn, vha, 0x02f3, "-> mpi_fwdump no buffer\n"); + } else if (vha->hw->mpi_fw_dumped) { + ql_log(ql_log_warn, vha, 0x02f4, + "-> MPI firmware already dumped (%p) -- ignoring request\n", + vha->hw->mpi_fw_dump); + } else { + struct fwdt *fwdt = &vha->hw->fwdt[1]; + ulong len; + void *buf = vha->hw->mpi_fw_dump; + + ql_log(ql_log_warn, vha, 0x02f5, "-> fwdt1 running...\n"); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0x02f6, + "-> fwdt1 no template\n"); + goto bailout; + } + len = qla27xx_execute_fwdt_template(vha, fwdt->template, buf); + if (len == 0) { + goto bailout; + } else if (len != fwdt->dump_size) { + ql_log(ql_log_warn, vha, 0x02f7, + "-> fwdt1 fwdump residual=%+ld\n", + fwdt->dump_size - len); + } else { + need_mpi_reset = 0; + } + + vha->hw->mpi_fw_dump_len = len; + vha->hw->mpi_fw_dumped = 1; + + ql_log(ql_log_warn, vha, 0x02f8, + "-> MPI firmware dump saved to buffer (%lu/%p)\n", + vha->host_no, vha->hw->mpi_fw_dump); + qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); + } + +bailout: + if (need_mpi_reset) + qla27xx_reset_mpi(vha); +#ifndef __CHECKER__ + if (!hardware_locked) + spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); +#endif +} + void qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) { @@ -1015,30 +1098,25 @@ qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) vha->hw->fw_dump); } else { struct fwdt *fwdt = vha->hw->fwdt; - uint j; ulong len; void *buf = vha->hw->fw_dump; - uint count = vha->hw->fw_dump_mpi ? 2 : 1; - for (j = 0; j < count; j++, fwdt++, buf += len) { - ql_log(ql_log_warn, vha, 0xd011, - "-> fwdt%u running...\n", j); - if (!fwdt->template) { - ql_log(ql_log_warn, vha, 0xd012, - "-> fwdt%u no template\n", j); - break; - } - len = qla27xx_execute_fwdt_template(vha, - fwdt->template, buf); - if (len == 0) { - goto bailout; - } else if (len != fwdt->dump_size) { - ql_log(ql_log_warn, vha, 0xd013, - "-> fwdt%u fwdump residual=%+ld\n", - j, fwdt->dump_size - len); - } + ql_log(ql_log_warn, vha, 0xd011, "-> fwdt0 running...\n"); + if (!fwdt->template) { + ql_log(ql_log_warn, vha, 0xd012, + "-> fwdt0 no template\n"); + goto bailout; } - vha->hw->fw_dump_len = buf - (void *)vha->hw->fw_dump; + len = qla27xx_execute_fwdt_template(vha, fwdt->template, buf); + if (len == 0) { + goto bailout; + } else if (len != fwdt->dump_size) { + ql_log(ql_log_warn, vha, 0xd013, + "-> fwdt0 fwdump residual=%+ld\n", + fwdt->dump_size - len); + } + + vha->hw->fw_dump_len = len; vha->hw->fw_dumped = 1; ql_log(ql_log_warn, vha, 0xd015, @@ -1048,7 +1126,6 @@ qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) } bailout: - vha->hw->fw_dump_mpi = 0; #ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); diff --git a/qla2x00t-32gbit/trace/events/qla.h b/qla2x00t-32gbit/trace/events/qla.h new file mode 100644 index 000000000..737a667ab --- /dev/null +++ b/qla2x00t-32gbit/trace/events/qla.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#if !defined(_TRACE_QLA_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_QLA_H_ + +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM qla + +#define QLA_MSG_MAX 256 + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsuggest-attribute=format" + +DECLARE_EVENT_CLASS(qla_log_event, + TP_PROTO(const char *buf, + struct va_format *vaf), + + TP_ARGS(buf, vaf), + + TP_STRUCT__entry( + __string(buf, buf) + __dynamic_array(char, msg, QLA_MSG_MAX) + ), + TP_fast_assign( + __assign_str(buf, buf); + vsnprintf(__get_str(msg), QLA_MSG_MAX, vaf->fmt, *vaf->va); + ), + + TP_printk("%s %s", __get_str(buf), __get_str(msg)) +); + +DEFINE_EVENT(qla_log_event, ql_dbg_log, + TP_PROTO(const char *buf, struct va_format *vaf), + TP_ARGS(buf, vaf) +); + +#pragma GCC diagnostic pop + +#endif /* _TRACE_QLA_H */ + +#define TRACE_INCLUDE_FILE qla + +#include