]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: qla2xxx: Fix reset of MPI firmware
authorArun Easi <aeasi@marvell.com>
Tue, 29 Sep 2020 10:21:49 +0000 (03:21 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Nov 2020 10:51:35 +0000 (11:51 +0100)
commit 3e6efab865ac943f4ec43913eb665695737112b0 upstream.

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: cbb01c2f2f63 ("scsi: qla2xxx: Fix MPI failure AEN (8200) handling")
Cc: stable@vger.kernel.org
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_tmpl.c

index 5d93ccc73153514157272ee31d580eb89a7a9d9c..5ab955007a07be84cf4a547f965d5f5fbb6c3779 100644 (file)
@@ -157,6 +157,14 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj,
                               vha->host_no);
                }
                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;
 }
@@ -744,8 +752,6 @@ 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) !=
index 0ced18f3104e541d9caa2969c5adc2fd07878adc..76711b34643a86685dc6bd1baca35f5470146ebf 100644 (file)
@@ -938,6 +938,5 @@ 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 */
index 8d4b651e14422b891698eb31881e0c5b69555dbb..91f2cfc12aaa2fe9f4e3b4e64aaa0f0dd8d570ca 100644 (file)
@@ -3298,6 +3298,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
                            j, fwdt->dump_size);
                        dump_size += fwdt->dump_size;
                }
+               /* Add space for spare MPI fw dump. */
+               dump_size += ha->fwdt[1].dump_size;
        } else {
                req_q_size = req->length * sizeof(request_t);
                rsp_q_size = rsp->length * sizeof(response_t);
index 8dc82cfd38b271678de36f325ef6138c68433a24..2847243f6cfd3fda41e01924953943ee81447728 100644 (file)
 #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)
-{
-       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
 qla27xx_insert16(uint16_t value, void *buf, ulong *len)
 {
@@ -1028,7 +1001,6 @@ void
 qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
 {
        ulong flags = 0;
-       bool need_mpi_reset = true;
 
 #ifndef __CHECKER__
        if (!hardware_locked)
@@ -1036,14 +1008,20 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
 #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;
+               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");
                if (!fwdt->template) {
@@ -1058,9 +1036,10 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
                        ql_log(ql_log_warn, vha, 0x02f7,
                               "-> fwdt1 fwdump residual=%+ld\n",
                               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_dumped = 1;
@@ -1072,8 +1051,6 @@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
        }
 
 bailout:
-       if (need_mpi_reset)
-               qla27xx_reset_mpi(vha);
 #ifndef __CHECKER__
        if (!hardware_locked)
                spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);