diff mbox series

[08/13] qla2xxx: Fix laggy FC remote port session recovery

Message ID 20220308082048.9774-9-njavali@marvell.com
State Superseded
Headers show
Series qla2xxx driver fixes | expand

Commit Message

Nilesh Javali March 8, 2022, 8:20 a.m. UTC
From: Quinn Tran <qutran@marvell.com>

For session recovery, driver relies on the dpc thread to
initiate certain operation. The dpc thread runs exclusively
without the Mailbox interface being occupied. Recent code change
for heartbeat check via mailbox cmd 0 is causing 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.

Cc: stable@vger.kernel.org
Fixes: d94d8158e184 ("scsi: qla2xxx: Add heartbeat check")
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  1 +
 drivers/scsi/qla2xxx/qla_os.c  | 20 +++++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

Comments

Himanshu Madhani March 9, 2022, 7:04 p.m. UTC | #1
> On Mar 8, 2022, at 12:20 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Quinn Tran <qutran@marvell.com>
> 
> For session recovery, driver relies on the dpc thread to
> initiate certain operation. The dpc thread runs exclusively
> without the Mailbox interface being occupied. Recent code change
> for heartbeat check via mailbox cmd 0 is causing 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.
> 
> Cc: stable@vger.kernel.org
> Fixes: d94d8158e184 ("scsi: qla2xxx: Add heartbeat check")
> Signed-off-by: Quinn Tran <qutran@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_def.h |  1 +
> drivers/scsi/qla2xxx/qla_os.c  | 20 +++++++++++++++++---
> 2 files changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index b0579bce5b88..80b02b077753 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -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;
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index d572a76d0fa0..89c7ac36a41a 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -7218,7 +7218,7 @@ static bool qla_do_heartbeat(struct scsi_qla_host *vha)
> 	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;
> 
> @@ -7228,8 +7228,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);
> +	}
> }
> 
> /**************************************************************************
> @@ -7420,6 +7431,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) ||
> @@ -7452,9 +7465,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);
> }
> -- 
> 2.19.0.rc0
> 

Looks Good. 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	 Oracle Linux Engineering
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b0579bce5b88..80b02b077753 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -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;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d572a76d0fa0..89c7ac36a41a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -7218,7 +7218,7 @@  static bool qla_do_heartbeat(struct scsi_qla_host *vha)
 	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;
 
@@ -7228,8 +7228,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);
+	}
 }
 
 /**************************************************************************
@@ -7420,6 +7431,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) ||
@@ -7452,9 +7465,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);
 }