aboutsummaryrefslogtreecommitdiff
path: root/sys/cam/scsi/scsi_pass.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/scsi/scsi_pass.c')
-rw-r--r--sys/cam/scsi/scsi_pass.c102
1 files changed, 67 insertions, 35 deletions
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index 5d6febe74539..5a24f11e60e2 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
* Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
@@ -27,9 +27,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -128,7 +125,7 @@ struct pass_io_req {
struct pass_softc {
pass_state state;
pass_flags flags;
- u_int8_t pd_type;
+ uint8_t pd_type;
int open_count;
u_int maxio;
struct devstat *device_stats;
@@ -165,7 +162,7 @@ static periph_dtor_t passcleanup;
static periph_start_t passstart;
static void pass_shutdown_kqueue(void *context, int pending);
static void pass_add_physpath(void *context, int pending);
-static void passasync(void *callback_arg, u_int32_t code,
+static void passasync(void *callback_arg, uint32_t code,
struct cam_path *path, void *arg);
static void passdone(struct cam_periph *periph,
union ccb *done_ccb);
@@ -179,10 +176,12 @@ static int passmemsetup(struct cam_periph *periph,
struct pass_io_req *io_req);
static int passmemdone(struct cam_periph *periph,
struct pass_io_req *io_req);
-static int passerror(union ccb *ccb, u_int32_t cam_flags,
- u_int32_t sense_flags);
+static int passerror(union ccb *ccb, uint32_t cam_flags,
+ uint32_t sense_flags);
static int passsendccb(struct cam_periph *periph, union ccb *ccb,
union ccb *inccb);
+static void passflags(union ccb *ccb, uint32_t *cam_flags,
+ uint32_t *sense_flags);
static struct periph_driver passdriver =
{
@@ -397,6 +396,18 @@ passcleanup(struct cam_periph *periph)
*/
taskqueue_drain(taskqueue_thread, &softc->add_physpath_task);
+ /*
+ * It should be safe to destroy the zones from here, because all
+ * of the references to this peripheral have been freed, and all
+ * I/O has been terminated and freed. We check the zones for NULL
+ * because they may not have been allocated yet if the device went
+ * away before any asynchronous I/O has been issued.
+ */
+ if (softc->pass_zone != NULL)
+ uma_zdestroy(softc->pass_zone);
+ if (softc->pass_io_zone != NULL)
+ uma_zdestroy(softc->pass_io_zone);
+
cam_periph_lock(periph);
free(softc, M_DEVBUF);
@@ -445,8 +456,9 @@ pass_add_physpath(void *context, int pending)
"GEOM::physpath", periph->path) == 0
&& strlen(physpath) != 0) {
mtx_unlock(mtx);
- make_dev_physpath_alias(MAKEDEV_WAITOK, &softc->alias_dev,
- softc->dev, softc->alias_dev, physpath);
+ make_dev_physpath_alias(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME,
+ &softc->alias_dev, softc->dev,
+ softc->alias_dev, physpath);
mtx_lock(mtx);
}
@@ -470,7 +482,7 @@ out:
}
static void
-passasync(void *callback_arg, u_int32_t code,
+passasync(void *callback_arg, uint32_t code,
struct cam_path *path, void *arg)
{
struct cam_periph *periph;
@@ -899,19 +911,17 @@ passdone(struct cam_periph *periph, union ccb *done_ccb)
xpt_print(periph->path, "%s: called for user CCB %p\n",
__func__, io_req->user_ccb_ptr);
#endif
- if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
- && (done_ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER)
- && ((io_req->flags & PASS_IO_ABANDONED) == 0)) {
+ if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) &&
+ ((io_req->flags & PASS_IO_ABANDONED) == 0)) {
int error;
+ uint32_t cam_flags, sense_flags;
- error = passerror(done_ccb, CAM_RETRY_SELTO,
- SF_RETRY_UA | SF_NO_PRINT);
+ passflags(done_ccb, &cam_flags, &sense_flags);
+ error = passerror(done_ccb, cam_flags, sense_flags);
if (error == ERESTART) {
- /*
- * A retry was scheduled, so
- * just return.
- */
+ KASSERT(((sense_flags & SF_NO_RETRY) == 0),
+ ("passerror returned ERESTART with no retry requested\n"));
return;
}
}
@@ -1073,7 +1083,7 @@ passcreatezone(struct cam_periph *periph)
/*
* Set the flags appropriately and notify any other waiters.
*/
- softc->flags &= PASS_FLAG_ZONE_INPROG;
+ softc->flags &= ~PASS_FLAG_ZONE_INPROG;
softc->flags |= PASS_FLAG_ZONE_VALID;
wakeup(&softc->pass_zone);
} else {
@@ -1107,7 +1117,7 @@ static void
passiocleanup(struct pass_softc *softc, struct pass_io_req *io_req)
{
union ccb *ccb;
- u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
+ uint8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
int i, numbufs;
ccb = &io_req->ccb;
@@ -1117,10 +1127,10 @@ passiocleanup(struct pass_softc *softc, struct pass_io_req *io_req)
numbufs = min(io_req->num_bufs, 2);
if (numbufs == 1) {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.matches;
} else {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
- data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.patterns;
+ data_ptrs[1] = (uint8_t **)&ccb->cdm.matches;
}
break;
case XPT_SCSI_IO:
@@ -1295,15 +1305,15 @@ passmemsetup(struct cam_periph *periph, struct pass_io_req *io_req)
return(EINVAL);
}
if (ccb->cdm.pattern_buf_len > 0) {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.patterns;
lengths[0] = ccb->cdm.pattern_buf_len;
dirs[0] = CAM_DIR_OUT;
- data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[1] = (uint8_t **)&ccb->cdm.matches;
lengths[1] = ccb->cdm.match_buf_len;
dirs[1] = CAM_DIR_IN;
numbufs = 2;
} else {
- data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
+ data_ptrs[0] = (uint8_t **)&ccb->cdm.matches;
lengths[0] = ccb->cdm.match_buf_len;
dirs[0] = CAM_DIR_IN;
numbufs = 1;
@@ -2217,24 +2227,46 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
* that request. Otherwise, it's up to the user to perform any
* error recovery.
*/
- cam_periph_runccb(ccb, (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
- passerror : NULL, /* cam_flags */ CAM_RETRY_SELTO,
- /* sense_flags */ SF_RETRY_UA | SF_NO_PRINT,
- softc->device_stats);
+ {
+ uint32_t cam_flags, sense_flags;
+
+ passflags(ccb, &cam_flags, &sense_flags);
+ cam_periph_runccb(ccb, passerror, cam_flags,
+ sense_flags, softc->device_stats);
+ }
cam_periph_unlock(periph);
- cam_periph_unmapmem(ccb, &mapinfo);
+ error = cam_periph_unmapmem(ccb, &mapinfo);
cam_periph_lock(periph);
ccb->ccb_h.cbfcnp = NULL;
ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
bcopy(ccb, inccb, sizeof(union ccb));
- return(0);
+ return (error);
+}
+
+/*
+ * Set the cam_flags and sense_flags based on whether or not the request wants
+ * error recovery. In order to log errors via devctl, we need to do at least
+ * minimal recovery. We do this by not retrying unit attention (we let the
+ * requester do it, or not, if appropriate) and specifically asking for no
+ * recovery, like we do during device probing.
+ */
+static void
+passflags(union ccb *ccb, uint32_t *cam_flags, uint32_t *sense_flags)
+{
+ if ((ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) != 0) {
+ *cam_flags = CAM_RETRY_SELTO;
+ *sense_flags = SF_RETRY_UA | SF_NO_PRINT;
+ } else {
+ *cam_flags = 0;
+ *sense_flags = SF_NO_RETRY | SF_NO_RECOVERY | SF_NO_PRINT;
+ }
}
static int
-passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
+passerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags)
{
return(cam_periph_error(ccb, cam_flags, sense_flags));