| From a665e5ae1e4831b0f215184d154ad9654889dc7b Mon Sep 17 00:00:00 2001 |
| From: Quinn Tran <quinn.tran@cavium.com> |
| Date: Wed, 15 Mar 2017 09:48:45 -0700 |
| Subject: [PATCH] qla2xxx: Fix request queue corruption. |
| |
| commit 8b666809e10cda9814af3e8be339d35b83909056 upstream. |
| |
| When FW notify driver or driver detects low FW resource, |
| driver tries to send out Busy SCSI Status to tell Initiator |
| side to back off. During the send process, the lock was not held. |
| |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Quinn Tran <quinn.tran@qlogic.com> |
| Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> |
| Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c |
| index c6c3b97a1e93..feab7ea8e823 100644 |
| --- a/drivers/scsi/qla2xxx/qla_target.c |
| +++ b/drivers/scsi/qla2xxx/qla_target.c |
| @@ -5375,16 +5375,22 @@ qlt_send_busy(struct scsi_qla_host *vha, |
| |
| static int |
| qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, |
| - struct atio_from_isp *atio) |
| + struct atio_from_isp *atio, bool ha_locked) |
| { |
| struct qla_hw_data *ha = vha->hw; |
| uint16_t status; |
| + unsigned long flags; |
| |
| if (ha->tgt.num_pend_cmds < Q_FULL_THRESH_HOLD(ha)) |
| return 0; |
| |
| + if (!ha_locked) |
| + spin_lock_irqsave(&ha->hardware_lock, flags); |
| status = temp_sam_status; |
| qlt_send_busy(vha, atio, status); |
| + if (!ha_locked) |
| + spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| + |
| return 1; |
| } |
| |
| @@ -5429,7 +5435,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, |
| |
| |
| if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) { |
| - rc = qlt_chk_qfull_thresh_hold(vha, atio); |
| + rc = qlt_chk_qfull_thresh_hold(vha, atio, ha_locked); |
| if (rc != 0) { |
| tgt->atio_irq_cmd_count--; |
| return; |
| @@ -5552,7 +5558,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) |
| break; |
| } |
| |
| - rc = qlt_chk_qfull_thresh_hold(vha, atio); |
| + rc = qlt_chk_qfull_thresh_hold(vha, atio, true); |
| if (rc != 0) { |
| tgt->irq_cmd_count--; |
| return; |
| -- |
| 2.12.0 |
| |