Simplify the checking of flags for cam_periph_mapmem(). This gets rid of
a lot of code redundancy and grossness at very minor expense. Reviewed by: smh Obtained from: Netflix MFC after: 3 days
This commit is contained in:
parent
ca8a27d4b1
commit
95fbded695
@ -681,9 +681,9 @@ camperiphfree(struct cam_periph *periph)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Map user virtual pointers into kernel virtual address space, so we can
|
* Map user virtual pointers into kernel virtual address space, so we can
|
||||||
* access the memory. This won't work on physical pointers, for now it's
|
* access the memory. This is now a generic function that centralizes most
|
||||||
* up to the caller to check for that. (XXX KDM -- should we do that here
|
* of the sanity checks on the data flags, if any.
|
||||||
* instead?) This also only works for up to MAXPHYS memory. Since we use
|
* This also only works for up to MAXPHYS memory. Since we use
|
||||||
* buffers to map stuff in and out, we're limited to the buffer size.
|
* buffers to map stuff in and out, we're limited to the buffer size.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -728,9 +728,8 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
|
|||||||
case XPT_CONT_TARGET_IO:
|
case XPT_CONT_TARGET_IO:
|
||||||
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
|
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
|
||||||
return(0);
|
return(0);
|
||||||
KASSERT((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR,
|
if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR)
|
||||||
("not VADDR for SCSI_IO %p %x\n", ccb, ccb->ccb_h.flags));
|
return (EINVAL);
|
||||||
|
|
||||||
data_ptrs[0] = &ccb->csio.data_ptr;
|
data_ptrs[0] = &ccb->csio.data_ptr;
|
||||||
lengths[0] = ccb->csio.dxfer_len;
|
lengths[0] = ccb->csio.dxfer_len;
|
||||||
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
|
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
|
||||||
@ -739,9 +738,8 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
|
|||||||
case XPT_ATA_IO:
|
case XPT_ATA_IO:
|
||||||
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
|
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
|
||||||
return(0);
|
return(0);
|
||||||
KASSERT((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR,
|
if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR)
|
||||||
("not VADDR for ATA_IO %p %x\n", ccb, ccb->ccb_h.flags));
|
return (EINVAL);
|
||||||
|
|
||||||
data_ptrs[0] = &ccb->ataio.data_ptr;
|
data_ptrs[0] = &ccb->ataio.data_ptr;
|
||||||
lengths[0] = ccb->ataio.dxfer_len;
|
lengths[0] = ccb->ataio.dxfer_len;
|
||||||
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
|
dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
|
||||||
@ -812,8 +810,12 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this keeps the current process from getting swapped */
|
|
||||||
/*
|
/*
|
||||||
|
* This keeps the the kernel stack of current thread from getting
|
||||||
|
* swapped. In low-memory situations where the kernel stack might
|
||||||
|
* otherwise get swapped out, this holds it and allows the thread
|
||||||
|
* to make progress and release the kernel mapped pages sooner.
|
||||||
|
*
|
||||||
* XXX KDM should I use P_NOSWAP instead?
|
* XXX KDM should I use P_NOSWAP instead?
|
||||||
*/
|
*/
|
||||||
PHOLD(curproc);
|
PHOLD(curproc);
|
||||||
@ -885,8 +887,7 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
|
|||||||
u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
|
u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
|
||||||
|
|
||||||
if (mapinfo->num_bufs_used <= 0) {
|
if (mapinfo->num_bufs_used <= 0) {
|
||||||
/* allow ourselves to be swapped once again */
|
/* nothing to free and the process wasn't held. */
|
||||||
PRELE(curproc);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,12 +668,11 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
|
|||||||
{
|
{
|
||||||
struct pass_softc *softc;
|
struct pass_softc *softc;
|
||||||
struct cam_periph_map_info mapinfo;
|
struct cam_periph_map_info mapinfo;
|
||||||
int error, need_unmap;
|
xpt_opcode fc;
|
||||||
|
int error;
|
||||||
|
|
||||||
softc = (struct pass_softc *)periph->softc;
|
softc = (struct pass_softc *)periph->softc;
|
||||||
|
|
||||||
need_unmap = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are some fields in the CCB header that need to be
|
* There are some fields in the CCB header that need to be
|
||||||
* preserved, the rest we get from the user.
|
* preserved, the rest we get from the user.
|
||||||
@ -687,28 +686,13 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
|
|||||||
ccb->ccb_h.cbfcnp = passdone;
|
ccb->ccb_h.cbfcnp = passdone;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We only attempt to map the user memory into kernel space
|
* Let cam_periph_mapmem do a sanity check on the data pointer format.
|
||||||
* if they haven't passed in a physical memory pointer,
|
* Even if no data transfer is needed, it's a cheap check and it
|
||||||
* and if there is actually an I/O operation to perform.
|
* simplifies the code.
|
||||||
* cam_periph_mapmem() supports SCSI, ATA, SMP, ADVINFO and device
|
|
||||||
* match CCBs. For the SCSI, ATA and ADVINFO CCBs, we only pass the
|
|
||||||
* CCB in if there's actually data to map. cam_periph_mapmem() will
|
|
||||||
* do the right thing, even if there isn't data to map, but since CCBs
|
|
||||||
* without data are a reasonably common occurrence (e.g. test unit
|
|
||||||
* ready), it will save a few cycles if we check for it here.
|
|
||||||
*
|
|
||||||
* XXX What happens if a sg list is supplied? We don't filter that
|
|
||||||
* out.
|
|
||||||
*/
|
*/
|
||||||
if (((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR)
|
fc = ccb->ccb_h.func_code;
|
||||||
&& (((ccb->ccb_h.func_code == XPT_SCSI_IO ||
|
if ((fc == XPT_SCSI_IO) || (fc == XPT_ATA_IO) || (fc == XPT_SMP_IO)
|
||||||
ccb->ccb_h.func_code == XPT_ATA_IO)
|
|| (fc == XPT_DEV_MATCH) || (fc == XPT_DEV_ADVINFO)) {
|
||||||
&& ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE))
|
|
||||||
|| (ccb->ccb_h.func_code == XPT_DEV_MATCH)
|
|
||||||
|| (ccb->ccb_h.func_code == XPT_SMP_IO)
|
|
||||||
|| ((ccb->ccb_h.func_code == XPT_DEV_ADVINFO)
|
|
||||||
&& (ccb->cdai.bufsiz > 0)))) {
|
|
||||||
|
|
||||||
bzero(&mapinfo, sizeof(mapinfo));
|
bzero(&mapinfo, sizeof(mapinfo));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -726,13 +710,9 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
|
|||||||
*/
|
*/
|
||||||
if (error)
|
if (error)
|
||||||
return(error);
|
return(error);
|
||||||
|
} else
|
||||||
/*
|
/* Ensure that the unmap call later on is a no-op. */
|
||||||
* We successfully mapped the memory in, so we need to
|
mapinfo.num_bufs_used = 0;
|
||||||
* unmap it when the transaction is done.
|
|
||||||
*/
|
|
||||||
need_unmap = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the user wants us to perform any error recovery, then honor
|
* If the user wants us to perform any error recovery, then honor
|
||||||
@ -744,8 +724,7 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
|
|||||||
SF_RETRY_UA : SF_NO_RECOVERY) | SF_NO_PRINT,
|
SF_RETRY_UA : SF_NO_RECOVERY) | SF_NO_PRINT,
|
||||||
softc->device_stats);
|
softc->device_stats);
|
||||||
|
|
||||||
if (need_unmap != 0)
|
cam_periph_unmapmem(ccb, &mapinfo);
|
||||||
cam_periph_unmapmem(ccb, &mapinfo);
|
|
||||||
|
|
||||||
ccb->ccb_h.cbfcnp = NULL;
|
ccb->ccb_h.cbfcnp = NULL;
|
||||||
ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
|
ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
|
||||||
|
@ -946,25 +946,23 @@ sgsendccb(struct cam_periph *periph, union ccb *ccb)
|
|||||||
{
|
{
|
||||||
struct sg_softc *softc;
|
struct sg_softc *softc;
|
||||||
struct cam_periph_map_info mapinfo;
|
struct cam_periph_map_info mapinfo;
|
||||||
int error, need_unmap = 0;
|
int error;
|
||||||
|
|
||||||
softc = periph->softc;
|
softc = periph->softc;
|
||||||
if (((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
|
bzero(&mapinfo, sizeof(mapinfo));
|
||||||
&& (ccb->csio.data_ptr != NULL)) {
|
|
||||||
bzero(&mapinfo, sizeof(mapinfo));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cam_periph_mapmem calls into proc and vm functions that can
|
* cam_periph_mapmem calls into proc and vm functions that can
|
||||||
* sleep as well as trigger I/O, so we can't hold the lock.
|
* sleep as well as trigger I/O, so we can't hold the lock.
|
||||||
* Dropping it here is reasonably safe.
|
* Dropping it here is reasonably safe.
|
||||||
*/
|
* The only CCB opcode that is possible here is XPT_SCSI_IO, no
|
||||||
cam_periph_unlock(periph);
|
* need for additional checks.
|
||||||
error = cam_periph_mapmem(ccb, &mapinfo);
|
*/
|
||||||
cam_periph_lock(periph);
|
cam_periph_unlock(periph);
|
||||||
if (error)
|
error = cam_periph_mapmem(ccb, &mapinfo);
|
||||||
return (error);
|
cam_periph_lock(periph);
|
||||||
need_unmap = 1;
|
if (error)
|
||||||
}
|
return (error);
|
||||||
|
|
||||||
error = cam_periph_runccb(ccb,
|
error = cam_periph_runccb(ccb,
|
||||||
sgerror,
|
sgerror,
|
||||||
@ -972,8 +970,7 @@ sgsendccb(struct cam_periph *periph, union ccb *ccb)
|
|||||||
SF_RETRY_UA,
|
SF_RETRY_UA,
|
||||||
softc->device_stats);
|
softc->device_stats);
|
||||||
|
|
||||||
if (need_unmap)
|
cam_periph_unmapmem(ccb, &mapinfo);
|
||||||
cam_periph_unmapmem(ccb, &mapinfo);
|
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
@ -726,21 +726,8 @@ targsendccb(struct targ_softc *softc, union ccb *ccb,
|
|||||||
ccb_h->cbfcnp = targdone;
|
ccb_h->cbfcnp = targdone;
|
||||||
ccb_h->targ_descr = descr;
|
ccb_h->targ_descr = descr;
|
||||||
|
|
||||||
/*
|
if ((ccb_h->func_code == XPT_CONT_TARGET_IO) ||
|
||||||
* We only attempt to map the user memory into kernel space
|
(ccb_h->func_code == XPT_DEV_MATCH)) {
|
||||||
* if they haven't passed in a physical memory pointer,
|
|
||||||
* and if there is actually an I/O operation to perform.
|
|
||||||
* Right now cam_periph_mapmem() only supports SCSI and device
|
|
||||||
* match CCBs. For the SCSI CCBs, we only pass the CCB in if
|
|
||||||
* there's actually data to map. cam_periph_mapmem() will do the
|
|
||||||
* right thing, even if there isn't data to map, but since CCBs
|
|
||||||
* without data are a reasonably common occurrence (e.g. test unit
|
|
||||||
* ready), it will save a few cycles if we check for it here.
|
|
||||||
*/
|
|
||||||
if (((ccb_h->flags & CAM_DATA_MASK) == CAM_DATA_VADDR)
|
|
||||||
&& (((ccb_h->func_code == XPT_CONT_TARGET_IO)
|
|
||||||
&& ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE))
|
|
||||||
|| (ccb_h->func_code == XPT_DEV_MATCH))) {
|
|
||||||
|
|
||||||
error = cam_periph_mapmem(ccb, mapinfo);
|
error = cam_periph_mapmem(ccb, mapinfo);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user