git: fd02926a68c9 - main - cam: Properly mask out the status bits to get completion code

From: Warner Losh <imp_at_FreeBSD.org>
Date: Sat, 15 Apr 2023 22:32:45 UTC
The branch main has been updated by imp:

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

commit fd02926a68c9570f00f7e50d64c1d0673581fb35
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2023-04-14 14:32:20 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2023-04-15 22:32:41 +0000

    cam: Properly mask out the status bits to get completion code
    
    ccb_h.status has two parts: the actual status and some addition bits to
    indicate additional information. It must be masked before comparing
    against completion codes. Add new inline function cam_ccb_success to
    simplify this to test whether or not the request succeeded. Most of the
    code already does this, but a few places don't (the rest likely should
    be converted to use cam_ccb_status and/or cam_ccb_success, but that's
    for another day). This caused at least one bug in recognizing devices
    behind a SATA port multiplexer, though some of these checks were
    fine with the special knowledge of the code paths involved.
    
    PR:                     270459
    Sponsored by:           Netflix
    MFC After:              1 week (and maybe a EN requst)
    Reviewed by:            ken, mav
    Differential Revision:  https://reviews.freebsd.org/D39572
---
 sys/cam/ata/ata_xpt.c       | 4 ++--
 sys/cam/cam_ccb.h           | 6 ++++++
 sys/cam/cam_xpt.c           | 2 +-
 sys/cam/nvme/nvme_da.c      | 3 +--
 sys/cam/scsi/scsi_enc_ses.c | 4 ++--
 5 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 2b299412b48e..643508c5d395 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -1003,7 +1003,7 @@ noerror:
 		    path->bus->sim->max_tagged_dev_openings != 0) {
 			/* Check if the SIM does not want queued commands. */
 			xpt_path_inq(&cpi, path);
-			if (cpi.ccb_h.status == CAM_REQ_CMP &&
+			if (cam_ccb_success((union ccb *)&cpi) &&
 			    (cpi.hba_inquiry & PI_TAG_ABLE)) {
 				/* Report SIM which tags are allowed. */
 				bzero(&cts, sizeof(cts));
@@ -1481,7 +1481,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
 		/* If there is PMP... */
 		if ((scan_info->cpi->hba_inquiry & PI_SATAPM) &&
 		    (scan_info->counter == scan_info->cpi->max_target)) {
-			if (work_ccb->ccb_h.status == CAM_REQ_CMP) {
+			if (cam_ccb_success(work_ccb)) {
 				/* everything else will be probed by it */
 				/* Free the current request path- we're done with it. */
 				xpt_free_path(work_ccb->ccb_h.path);
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 1ae310d399b7..a6b12b6a3584 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -1516,6 +1516,12 @@ cam_ccb_status(union ccb *ccb)
 	return ((cam_status)(ccb->ccb_h.status & CAM_STATUS_MASK));
 }
 
+static inline bool
+cam_ccb_success(union ccb *ccb)
+{
+	return (cam_ccb_status(ccb) == CAM_REQ_CMP);
+}
+
 void cam_calc_geometry(struct ccb_calc_geometry *ccg, int extended);
 
 static __inline void
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index f3e9f2772e62..efedcaf5cf92 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -4018,7 +4018,7 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, uint32_t bus)
 
 	xpt_path_inq(&cpi, path);
 
-	if (cpi.ccb_h.status == CAM_REQ_CMP) {
+	if (cam_ccb_success((union ccb *)&cpi)) {
 		struct xpt_xport **xpt;
 
 		SET_FOREACH(xpt, cam_xpt_xport_set) {
diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c
index 51689d0e4a23..94915ec6a726 100644
--- a/sys/cam/nvme/nvme_da.c
+++ b/sys/cam/nvme/nvme_da.c
@@ -441,8 +441,7 @@ ndaioctl(struct disk *dp, u_long cmd, void *data, int fflag,
 		 */
 		cam_periph_unlock(periph);
 		cam_periph_unmapmem(ccb, &mapinfo);
-		error = (ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP ?
-		    0 : EIO;
+		error = cam_ccb_success(ccb) ? 0 : EIO;
 out:
 		cam_periph_lock(periph);
 		xpt_release_ccb(ccb);
diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index 557038d9b9f6..58b0a5af74cd 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -986,7 +986,7 @@ ses_paths_iter(enc_softc_t *enc, enc_element_t *elm,
 			xpt_setup_ccb(&cgd.ccb_h, path, CAM_PRIORITY_NORMAL);
 			cgd.ccb_h.func_code = XPT_GDEV_TYPE;
 			xpt_action((union ccb *)&cgd);
-			if (cgd.ccb_h.status == CAM_REQ_CMP)
+			if (cam_ccb_success((union ccb *)&cgd))
 				callback(enc, elm, path, callback_arg);
 
 			xpt_free_path(path);
@@ -1065,7 +1065,7 @@ ses_setphyspath_callback(enc_softc_t *enc, enc_element_t *elm,
 		xpt_action((union ccb *)&cdai);
 		if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
 			cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
-		if (cdai.ccb_h.status == CAM_REQ_CMP)
+		if (cam_ccb_success((union ccb *)&cdai))
 			args->num_set++;
 	}
 	xpt_path_unlock(path);