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

scsi: qla2xxx: Fix response queue handler reading stale packets

On some platforms, the current logic of relying on finding new packet
solely based on signature pattern can lead to driver reading stale
packets. Though this is a bug in those platforms, reduce such exposures by
limiting reading packets until the IN pointer.

Two module parameters are introduced:

  ql2xrspq_follow_inptr:

    When set, on newer adapters that has queue pointer shadowing, look for
    response packets only until response queue in pointer.

    When reset, response packets are read based on a signature pattern
    logic (old way).

  ql2xrspq_follow_inptr_legacy:

    Like ql2xrspq_follow_inptr, but for those adapters where there is no
    queue pointer shadowing.

Link: https://lore.kernel.org/r/20220713052045.10683-5-njavali@marvell.com
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 6c96a3c7
......@@ -193,6 +193,8 @@ extern int ql2xsecenable;
extern int ql2xenforce_iocb_limit;
extern int ql2xabts_wait_nvme;
extern u32 ql2xnvme_queues;
extern int ql2xrspq_follow_inptr;
extern int ql2xrspq_follow_inptr_legacy;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
......
......@@ -3780,6 +3780,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
struct qla_hw_data *ha = vha->hw;
struct purex_entry_24xx *purex_entry;
struct purex_item *pure_item;
u16 rsp_in = 0;
int follow_inptr, is_shadow_hba;
if (!ha->flags.fw_started)
return;
......@@ -3789,7 +3791,25 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
qla_cpu_update(rsp->qpair, smp_processor_id());
}
while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
#define __update_rsp_in(_update, _is_shadow_hba, _rsp, _rsp_in) \
do { \
if (_update) { \
_rsp_in = _is_shadow_hba ? *(_rsp)->in_ptr : \
rd_reg_dword_relaxed((_rsp)->rsp_q_in); \
} \
} while (0)
is_shadow_hba = IS_SHADOW_REG_CAPABLE(ha);
follow_inptr = is_shadow_hba ? ql2xrspq_follow_inptr :
ql2xrspq_follow_inptr_legacy;
__update_rsp_in(follow_inptr, is_shadow_hba, rsp, rsp_in);
while ((likely(follow_inptr &&
rsp->ring_index != rsp_in &&
rsp->ring_ptr->signature != RESPONSE_PROCESSED)) ||
(!follow_inptr &&
rsp->ring_ptr->signature != RESPONSE_PROCESSED)) {
pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
rsp->ring_index++;
......@@ -3902,6 +3922,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
}
pure_item = qla27xx_copy_fpin_pkt(vha,
(void **)&pkt, &rsp);
__update_rsp_in(follow_inptr, is_shadow_hba,
rsp, rsp_in);
if (!pure_item)
break;
qla24xx_queue_purex_item(vha, pure_item,
......
......@@ -338,6 +338,16 @@ module_param(ql2xdelay_before_pci_error_handling, uint, 0644);
MODULE_PARM_DESC(ql2xdelay_before_pci_error_handling,
"Number of seconds delayed before qla begin PCI error self-handling (default: 5).\n");
int ql2xrspq_follow_inptr = 1;
module_param(ql2xrspq_follow_inptr, int, 0644);
MODULE_PARM_DESC(ql2xrspq_follow_inptr,
"Follow RSP IN pointer for RSP updates for HBAs 27xx and newer (default: 1).");
int ql2xrspq_follow_inptr_legacy = 1;
module_param(ql2xrspq_follow_inptr_legacy, int, 0644);
MODULE_PARM_DESC(ql2xrspq_follow_inptr_legacy,
"Follow RSP IN pointer for RSP updates for HBAs older than 27XX. (default: 1).");
static void qla2x00_clear_drv_active(struct qla_hw_data *);
static void qla2x00_free_device(scsi_qla_host_t *);
static int qla2xxx_map_queues(struct Scsi_Host *shost);
......
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