Daniel Wagner 603556
From: Arun Easi <aeasi@marvell.com>
Daniel Wagner 603556
Date: Tue, 12 Jul 2022 22:20:39 -0700
Daniel Wagner 603556
Subject: scsi: qla2xxx: Fix response queue handler reading stale packets
Denis Kirjanov 718367
Patch-mainline: v5.20-rc1
Daniel Wagner 603556
Git-commit: b1f707146923335849fb70237eec27d4d1ae7d62
Daniel Wagner 603556
References: bsc#1201651
Daniel Wagner 603556
Daniel Wagner 603556
On some platforms, the current logic of relying on finding new packet
Daniel Wagner 603556
solely based on signature pattern can lead to driver reading stale
Daniel Wagner 603556
packets. Though this is a bug in those platforms, reduce such exposures by
Daniel Wagner 603556
limiting reading packets until the IN pointer.
Daniel Wagner 603556
Daniel Wagner 603556
Two module parameters are introduced:
Daniel Wagner 603556
Daniel Wagner 603556
  ql2xrspq_follow_inptr:
Daniel Wagner 603556
Daniel Wagner 603556
    When set, on newer adapters that has queue pointer shadowing, look for
Daniel Wagner 603556
    response packets only until response queue in pointer.
Daniel Wagner 603556
Daniel Wagner 603556
    When reset, response packets are read based on a signature pattern
Daniel Wagner 603556
    logic (old way).
Daniel Wagner 603556
Daniel Wagner 603556
  ql2xrspq_follow_inptr_legacy:
Daniel Wagner 603556
Daniel Wagner 603556
    Like ql2xrspq_follow_inptr, but for those adapters where there is no
Daniel Wagner 603556
    queue pointer shadowing.
Daniel Wagner 603556
Daniel Wagner 603556
Link: https://lore.kernel.org/r/20220713052045.10683-5-njavali@marvell.com
Daniel Wagner 603556
Cc: stable@vger.kernel.org
Daniel Wagner 603556
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Daniel Wagner 603556
Signed-off-by: Arun Easi <aeasi@marvell.com>
Daniel Wagner 603556
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Daniel Wagner 603556
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner 603556
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner 603556
---
Daniel Wagner 603556
 drivers/scsi/qla2xxx/qla_gbl.h |    2 ++
Daniel Wagner 603556
 drivers/scsi/qla2xxx/qla_isr.c |   24 +++++++++++++++++++++++-
Daniel Wagner 603556
 drivers/scsi/qla2xxx/qla_os.c  |    9 +++++++++
Daniel Wagner 603556
 3 files changed, 34 insertions(+), 1 deletion(-)
Daniel Wagner 603556
Daniel Wagner 603556
--- a/drivers/scsi/qla2xxx/qla_gbl.h
Daniel Wagner 603556
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
Daniel Wagner 603556
@@ -195,6 +195,8 @@ extern int ql2xsecenable;
Daniel Wagner 603556
 extern int ql2xenforce_iocb_limit;
Daniel Wagner 603556
 extern int ql2xabts_wait_nvme;
Daniel Wagner 603556
 extern u32 ql2xnvme_queues;
Daniel Wagner 603556
+extern int ql2xrspq_follow_inptr;
Daniel Wagner 603556
+extern int ql2xrspq_follow_inptr_legacy;
Daniel Wagner 603556
 
Daniel Wagner 603556
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
Daniel Wagner 603556
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
Daniel Wagner 603556
--- a/drivers/scsi/qla2xxx/qla_isr.c
Daniel Wagner 603556
+++ b/drivers/scsi/qla2xxx/qla_isr.c
Daniel Wagner 603556
@@ -3790,6 +3790,8 @@ void qla24xx_process_response_queue(stru
Daniel Wagner 603556
 	struct qla_hw_data *ha = vha->hw;
Daniel Wagner 603556
 	struct purex_entry_24xx *purex_entry;
Daniel Wagner 603556
 	struct purex_item *pure_item;
Daniel Wagner 603556
+	u16 rsp_in = 0;
Daniel Wagner 603556
+	int follow_inptr, is_shadow_hba;
Daniel Wagner 603556
 
Daniel Wagner 603556
 	if (!ha->flags.fw_started)
Daniel Wagner 603556
 		return;
Daniel Wagner 603556
@@ -3799,7 +3801,25 @@ void qla24xx_process_response_queue(stru
Daniel Wagner 603556
 		qla_cpu_update(rsp->qpair, smp_processor_id());
Daniel Wagner 603556
 	}
Daniel Wagner 603556
 
Daniel Wagner 603556
-	while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
Daniel Wagner 603556
+#define __update_rsp_in(_update, _is_shadow_hba, _rsp, _rsp_in)		\
Daniel Wagner 603556
+	do {								\
Daniel Wagner 603556
+		if (_update) {						\
Daniel Wagner 603556
+			_rsp_in = _is_shadow_hba ? *(_rsp)->in_ptr :	\
Daniel Wagner 603556
+				rd_reg_dword_relaxed((_rsp)->rsp_q_in);	\
Daniel Wagner 603556
+		}							\
Daniel Wagner 603556
+	} while (0)
Daniel Wagner 603556
+
Daniel Wagner 603556
+	is_shadow_hba = IS_SHADOW_REG_CAPABLE(ha);
Daniel Wagner 603556
+	follow_inptr = is_shadow_hba ? ql2xrspq_follow_inptr :
Daniel Wagner 603556
+				ql2xrspq_follow_inptr_legacy;
Daniel Wagner 603556
+
Daniel Wagner 603556
+	__update_rsp_in(follow_inptr, is_shadow_hba, rsp, rsp_in);
Daniel Wagner 603556
+
Daniel Wagner 603556
+	while ((likely(follow_inptr &&
Daniel Wagner 603556
+		       rsp->ring_index != rsp_in &&
Daniel Wagner 603556
+		       rsp->ring_ptr->signature != RESPONSE_PROCESSED)) ||
Daniel Wagner 603556
+		       (!follow_inptr &&
Daniel Wagner 603556
+			rsp->ring_ptr->signature != RESPONSE_PROCESSED)) {
Daniel Wagner 603556
 		pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
Daniel Wagner 603556
 
Daniel Wagner 603556
 		rsp->ring_index++;
Daniel Wagner 603556
@@ -3912,6 +3932,8 @@ void qla24xx_process_response_queue(stru
Daniel Wagner 603556
 				}
Daniel Wagner 603556
 				pure_item = qla27xx_copy_fpin_pkt(vha,
Daniel Wagner 603556
 							  (void **)&pkt, &rsp;;
Daniel Wagner 603556
+				__update_rsp_in(follow_inptr, is_shadow_hba,
Daniel Wagner 603556
+						rsp, rsp_in);
Daniel Wagner 603556
 				if (!pure_item)
Daniel Wagner 603556
 					break;
Daniel Wagner 603556
 				qla24xx_queue_purex_item(vha, pure_item,
Daniel Wagner 603556
--- a/drivers/scsi/qla2xxx/qla_os.c
Daniel Wagner 603556
+++ b/drivers/scsi/qla2xxx/qla_os.c
Daniel Wagner 603556
@@ -339,6 +339,15 @@ module_param(ql2xabts_wait_nvme, int, 04
Daniel Wagner 603556
 MODULE_PARM_DESC(ql2xabts_wait_nvme,
Daniel Wagner 603556
 		 "To wait for ABTS response on I/O timeouts for NVMe. (default: 1)");
Daniel Wagner 603556
 
Daniel Wagner 603556
+int ql2xrspq_follow_inptr = 1;
Daniel Wagner 603556
+module_param(ql2xrspq_follow_inptr, int, 0644);
Daniel Wagner 603556
+MODULE_PARM_DESC(ql2xrspq_follow_inptr,
Daniel Wagner 603556
+		 "Follow RSP IN pointer for RSP updates for HBAs 27xx and newer (default: 1).");
Daniel Wagner 603556
+
Daniel Wagner 603556
+int ql2xrspq_follow_inptr_legacy = 1;
Daniel Wagner 603556
+module_param(ql2xrspq_follow_inptr_legacy, int, 0644);
Daniel Wagner 603556
+MODULE_PARM_DESC(ql2xrspq_follow_inptr_legacy,
Daniel Wagner 603556
+		 "Follow RSP IN pointer for RSP updates for HBAs older than 27XX. (default: 1).");
Daniel Wagner 603556
 
Daniel Wagner 603556
 u32 ql2xdelay_before_pci_error_handling = 5;
Daniel Wagner 603556
 module_param(ql2xdelay_before_pci_error_handling, uint, 0644);