diff options
author | Arun Easi <aeasi@marvell.com> | 2022-07-13 08:20:39 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2022-07-19 05:33:03 +0300 |
commit | b1f707146923335849fb70237eec27d4d1ae7d62 (patch) | |
tree | b12d90e669e8d870360c055b7a7295be5586a897 /drivers/scsi/qla2xxx/qla_isr.c | |
parent | 6c96a3c7d49593ef15805f5e497601c87695abc9 (diff) | |
download | linux-b1f707146923335849fb70237eec27d4d1ae7d62.tar.xz |
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: 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>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 4fa24d318f14..35b425c446b9 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -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 @@ process_err: } 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, |