Commit 3e6efab8 authored by Arun Easi's avatar Arun Easi Committed by Martin K. Petersen

scsi: qla2xxx: Fix reset of MPI firmware

Normally, the MPI firmware is reset when an MPI dump is collected.  If an
unsaved MPI dump exists in the driver, though, an alternate mechanism is
used. This mechanism, which was not fully correct, is not recommended and
instead an MPI dump template walk is suggested to perform the MPI reset.

To allow for the MPI dump template walk, extra space is reserved in the MPI
dump buffer which gets used only when there is already an MPI dump in
place.

Link: https://lore.kernel.org/r/20200929102152.32278-5-njavali@marvell.com
Fixes: cbb01c2f ("scsi: qla2xxx: Fix MPI failure AEN (8200) handling")
Cc: stable@vger.kernel.org
Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarArun Easi <aeasi@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7a6cdbd5
...@@ -157,6 +157,14 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj, ...@@ -157,6 +157,14 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
vha->host_no); vha->host_no);
} }
break; break;
case 10:
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
ql_log(ql_log_info, vha, 0x70e9,
"Issuing MPI firmware dump on host#%ld.\n",
vha->host_no);
ha->isp_ops->mpi_fw_dump(vha, 0);
}
break;
} }
return count; return count;
} }
...@@ -744,8 +752,6 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, ...@@ -744,8 +752,6 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP); qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP);
qla83xx_idc_unlock(vha, 0); qla83xx_idc_unlock(vha, 0);
break; break;
} else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
qla27xx_reset_mpi(vha);
} else { } else {
/* Make sure FC side is not in reset */ /* Make sure FC side is not in reset */
WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) != WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) !=
......
...@@ -945,6 +945,5 @@ extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp); ...@@ -945,6 +945,5 @@ extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp);
/* nvme.c */ /* nvme.c */
void qla_nvme_unregister_remote_port(struct fc_port *fcport); 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); void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
#endif /* _QLA_GBL_H */ #endif /* _QLA_GBL_H */
...@@ -3298,6 +3298,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) ...@@ -3298,6 +3298,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
j, fwdt->dump_size); j, fwdt->dump_size);
dump_size += fwdt->dump_size; dump_size += fwdt->dump_size;
} }
/* Add space for spare MPI fw dump. */
dump_size += ha->fwdt[1].dump_size;
} else { } else {
req_q_size = req->length * sizeof(request_t); req_q_size = req->length * sizeof(request_t);
rsp_q_size = rsp->length * sizeof(response_t); rsp_q_size = rsp->length * sizeof(response_t);
......
...@@ -12,33 +12,6 @@ ...@@ -12,33 +12,6 @@
#define IOBASE(vha) IOBAR(ISPREG(vha)) #define IOBASE(vha) IOBAR(ISPREG(vha))
#define INVALID_ENTRY ((struct qla27xx_fwdt_entry *)0xffffffffffffffffUL) #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)
{
struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
ql_dbg(ql_dbg_misc, vha, 0xd300,
"%s: addr/data = %xh/%xh\n", __func__, addr, data);
wrt_reg_dword(&reg->iobase_addr, 0x40);
wrt_reg_dword(&reg->iobase_c4, data);
wrt_reg_dword(&reg->iobase_window, 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 static inline void
qla27xx_insert16(uint16_t value, void *buf, ulong *len) qla27xx_insert16(uint16_t value, void *buf, ulong *len)
{ {
...@@ -1028,7 +1001,6 @@ void ...@@ -1028,7 +1001,6 @@ void
qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked) qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
{ {
ulong flags = 0; ulong flags = 0;
bool need_mpi_reset = true;
#ifndef __CHECKER__ #ifndef __CHECKER__
if (!hardware_locked) if (!hardware_locked)
...@@ -1036,14 +1008,20 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked) ...@@ -1036,14 +1008,20 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
#endif #endif
if (!vha->hw->mpi_fw_dump) { if (!vha->hw->mpi_fw_dump) {
ql_log(ql_log_warn, vha, 0x02f3, "-> mpi_fwdump no buffer\n"); 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 { } else {
struct fwdt *fwdt = &vha->hw->fwdt[1]; struct fwdt *fwdt = &vha->hw->fwdt[1];
ulong len; ulong len;
void *buf = vha->hw->mpi_fw_dump; void *buf = vha->hw->mpi_fw_dump;
bool walk_template_only = false;
if (vha->hw->mpi_fw_dumped) {
/* Use the spare area for any further dumps. */
buf += fwdt->dump_size;
walk_template_only = true;
ql_log(ql_log_warn, vha, 0x02f4,
"-> MPI firmware already dumped -- dump saving to temporary buffer %p.\n",
buf);
}
ql_log(ql_log_warn, vha, 0x02f5, "-> fwdt1 running...\n"); ql_log(ql_log_warn, vha, 0x02f5, "-> fwdt1 running...\n");
if (!fwdt->template) { if (!fwdt->template) {
...@@ -1058,9 +1036,10 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked) ...@@ -1058,9 +1036,10 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
ql_log(ql_log_warn, vha, 0x02f7, ql_log(ql_log_warn, vha, 0x02f7,
"-> fwdt1 fwdump residual=%+ld\n", "-> fwdt1 fwdump residual=%+ld\n",
fwdt->dump_size - len); fwdt->dump_size - len);
} else {
need_mpi_reset = false;
} }
vha->hw->stat.num_mpi_reset++;
if (walk_template_only)
goto bailout;
vha->hw->mpi_fw_dump_len = len; vha->hw->mpi_fw_dump_len = len;
vha->hw->mpi_fw_dumped = 1; vha->hw->mpi_fw_dumped = 1;
...@@ -1072,8 +1051,6 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked) ...@@ -1072,8 +1051,6 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
} }
bailout: bailout:
if (need_mpi_reset)
qla27xx_reset_mpi(vha);
#ifndef __CHECKER__ #ifndef __CHECKER__
if (!hardware_locked) if (!hardware_locked)
spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
......
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