git: 668615aea2c9 - stable/12 - ocs_fc: When commands complete with an error, freeze the device queue.

From: Ram Kishore Vegesna <ram_at_FreeBSD.org>
Date: Fri, 17 Dec 2021 10:03:53 UTC
The branch stable/12 has been updated by ram:

URL: https://cgit.FreeBSD.org/src/commit/?id=668615aea2c9e3ef33ebe23c497955a922fa20c8

commit 668615aea2c9e3ef33ebe23c497955a922fa20c8
Author:     Ram Kishore Vegesna <ram@FreeBSD.org>
AuthorDate: 2021-09-24 09:32:09 +0000
Commit:     Ram Kishore Vegesna <ram@FreeBSD.org>
CommitDate: 2021-12-17 09:57:50 +0000

    ocs_fc: When commands complete with an error, freeze the device queue.
    
    Proper error recovery depends on freezing the device queue when an
    error occurs, so we can recover from an error before sending
    additional commands.
    
    The ocs_fc(4) driver was not freezing the device queue for most
    SCSI errors, and that broke error recovery.
    
    sys/dev/ocs_fc/ocs_cam.c:
            In ocs_scsi_initiator_io_cb(), freeze the device queue if
            we're passing back status other than CAM_REQ_CMP.
    
    Submitted by: ken@kdm.org
    Reviewed by: mav, ken
    
    (cherry picked from commit d063d1bc928165e7798df5ec1c424794a1ec41e9)
---
 sys/dev/ocs_fc/ocs_cam.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/sys/dev/ocs_fc/ocs_cam.c b/sys/dev/ocs_fc/ocs_cam.c
index e5862f093ed3..c773eab105f0 100644
--- a/sys/dev/ocs_fc/ocs_cam.c
+++ b/sys/dev/ocs_fc/ocs_cam.c
@@ -1520,10 +1520,6 @@ static int32_t ocs_scsi_initiator_io_cb(ocs_io_t *io,
 		}
 	} else if (scsi_status != OCS_SCSI_STATUS_GOOD) {
 		ccb_status = CAM_REQ_CMP_ERR;
-		ocs_set_ccb_status(ccb, ccb_status);
-		csio->ccb_h.status |= CAM_DEV_QFRZN;
-		xpt_freeze_devq(csio->ccb_h.path, 1);
-
 	} else {
 		ccb_status = CAM_REQ_CMP;
 	}
@@ -1534,8 +1530,15 @@ static int32_t ocs_scsi_initiator_io_cb(ocs_io_t *io,
 
 	csio->ccb_h.ccb_io_ptr = NULL;
 	csio->ccb_h.ccb_ocs_ptr = NULL;
+
 	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 
+	if ((ccb_status != CAM_REQ_CMP) &&
+	    ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0)) {
+		ccb->ccb_h.status |= CAM_DEV_QFRZN;
+		xpt_freeze_devq(ccb->ccb_h.path, 1);
+	}
+
 	xpt_done(ccb);
 
 	return 0;