scsi: qla2xxx: Fix laggy FC remote port session recovery

[ Upstream commit 713b415726f100f6644971e75ebfe1edbef1a390 ]

For session recovery, driver relies on the dpc thread to initiate certain
operations. The dpc thread runs exclusively without the Mailbox interface
being occupied. A recent code change for heartbeat check via mailbox cmd 0
is preventing the dpc thread from carrying out its operation. This patch
allows the higher priority error recovery to run first before running the
lower priority heartbeat check.

Link: https://lore.kernel.org/r/20220310092604.22950-9-njavali@marvell.com
Fixes: d94d8158e1 ("scsi: qla2xxx: Add heartbeat check")
Cc: stable@vger.kernel.org
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Quinn Tran
2022-03-10 01:25:59 -08:00
committed by Greg Kroah-Hartman
parent 241afac69b
commit d451011991
2 changed files with 18 additions and 3 deletions

View File

@@ -4621,6 +4621,7 @@ struct qla_hw_data {
struct workqueue_struct *wq;
struct work_struct heartbeat_work;
struct qlfc_fw fw_buf;
unsigned long last_heartbeat_run_jiffies;
/* FCP_CMND priority support */
struct qla_fcp_prio_cfg *fcp_prio_cfg;

View File

@@ -7205,7 +7205,7 @@ skip:
return do_heartbeat;
}
static void qla_heart_beat(struct scsi_qla_host *vha)
static void qla_heart_beat(struct scsi_qla_host *vha, u16 dpc_started)
{
struct qla_hw_data *ha = vha->hw;
@@ -7215,8 +7215,19 @@ static void qla_heart_beat(struct scsi_qla_host *vha)
if (vha->hw->flags.eeh_busy || qla2x00_chip_is_down(vha))
return;
if (qla_do_heartbeat(vha))
/*
* dpc thread cannot run if heartbeat is running at the same time.
* We also do not want to starve heartbeat task. Therefore, do
* heartbeat task at least once every 5 seconds.
*/
if (dpc_started &&
time_before(jiffies, ha->last_heartbeat_run_jiffies + 5 * HZ))
return;
if (qla_do_heartbeat(vha)) {
ha->last_heartbeat_run_jiffies = jiffies;
queue_work(ha->wq, &ha->heartbeat_work);
}
}
/**************************************************************************
@@ -7407,6 +7418,8 @@ qla2x00_timer(struct timer_list *t)
start_dpc++;
}
/* borrowing w to signify dpc will run */
w = 0;
/* Schedule the DPC routine if needed */
if ((test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
@@ -7439,9 +7452,10 @@ qla2x00_timer(struct timer_list *t)
test_bit(RELOGIN_NEEDED, &vha->dpc_flags),
test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags));
qla2xxx_wake_dpc(vha);
w = 1;
}
qla_heart_beat(vha);
qla_heart_beat(vha, w);
qla2x00_restart_timer(vha, WATCH_INTERVAL);
}