aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2023-04-14 14:32:20 +0000
committerWarner Losh <imp@FreeBSD.org>2023-04-15 22:32:41 +0000
commitfd02926a68c9570f00f7e50d64c1d0673581fb35 (patch)
tree542fddc96c9211dddad3c1a05b44bdb2a922ad6f
parent63ee747febbf024be0aace61161241b53245449e (diff)
downloadsrc-fd02926a68c9570f00f7e50d64c1d0673581fb35.tar.gz
src-fd02926a68c9570f00f7e50d64c1d0673581fb35.zip
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
-rw-r--r--sys/cam/ata/ata_xpt.c4
-rw-r--r--sys/cam/cam_ccb.h6
-rw-r--r--sys/cam/cam_xpt.c2
-rw-r--r--sys/cam/nvme/nvme_da.c3
-rw-r--r--sys/cam/scsi/scsi_enc_ses.c4
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);