Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/cam_periph.c
Show First 20 Lines • Show All 1,154 Lines • ▼ Show 20 Lines | cam_periph_runccb(union ccb *ccb, | ||||
cam_flags camflags, | cam_flags camflags, | ||||
u_int32_t sense_flags), | u_int32_t sense_flags), | ||||
cam_flags camflags, u_int32_t sense_flags, | cam_flags camflags, u_int32_t sense_flags, | ||||
struct devstat *ds) | struct devstat *ds) | ||||
{ | { | ||||
struct bintime *starttime; | struct bintime *starttime; | ||||
struct bintime ltime; | struct bintime ltime; | ||||
int error; | int error; | ||||
bool sched_stopped; | |||||
struct mtx *periph_mtx; | |||||
struct cam_periph *periph; | |||||
uint32_t timeout = 1; | |||||
starttime = NULL; | starttime = NULL; | ||||
xpt_path_assert(ccb->ccb_h.path, MA_OWNED); | xpt_path_assert(ccb->ccb_h.path, MA_OWNED); | ||||
KASSERT((ccb->ccb_h.flags & CAM_UNLOCKED) == 0, | KASSERT((ccb->ccb_h.flags & CAM_UNLOCKED) == 0, | ||||
("%s: ccb=%p, func_code=%#x, flags=%#x", __func__, ccb, | ("%s: ccb=%p, func_code=%#x, flags=%#x", __func__, ccb, | ||||
ccb->ccb_h.func_code, ccb->ccb_h.flags)); | ccb->ccb_h.func_code, ccb->ccb_h.flags)); | ||||
/* | /* | ||||
* If the user has supplied a stats structure, and if we understand | * If the user has supplied a stats structure, and if we understand | ||||
* this particular type of ccb, record the transaction start. | * this particular type of ccb, record the transaction start. | ||||
*/ | */ | ||||
if (ds != NULL && | if (ds != NULL && | ||||
(ccb->ccb_h.func_code == XPT_SCSI_IO || | (ccb->ccb_h.func_code == XPT_SCSI_IO || | ||||
ccb->ccb_h.func_code == XPT_ATA_IO || | ccb->ccb_h.func_code == XPT_ATA_IO || | ||||
ccb->ccb_h.func_code == XPT_NVME_IO)) { | ccb->ccb_h.func_code == XPT_NVME_IO)) { | ||||
starttime = <ime; | starttime = <ime; | ||||
binuptime(starttime); | binuptime(starttime); | ||||
devstat_start_transaction(ds, starttime); | devstat_start_transaction(ds, starttime); | ||||
} | } | ||||
sched_stopped = SCHEDULER_STOPPED(); | |||||
ccb->ccb_h.cbfcnp = cam_periph_done; | ccb->ccb_h.cbfcnp = cam_periph_done; | ||||
xpt_action(ccb); | periph = xpt_path_periph(ccb->ccb_h.path); | ||||
periph_mtx = cam_periph_mtx(periph); | |||||
/* | |||||
* If we're polling, then we need to ensure that we have ample resources | |||||
* in the periph. We also need to drop the periph lock while we're polling. | |||||
* cam_periph_error can reschedule the ccb by calling xpt_action and returning | |||||
* ERESTART, so we have to effect the polling in the do loop below. | |||||
*/ | |||||
if (sched_stopped) { | |||||
mtx_unlock(periph_mtx); | |||||
timeout = xpt_poll_setup(ccb); | |||||
} | |||||
if (timeout == 0) { | |||||
ccb->ccb_h.status = CAM_RESRC_UNAVAIL; | |||||
error = EBUSY; | |||||
} else { | |||||
xpt_action(ccb); | |||||
do { | do { | ||||
if (!sched_stopped) | |||||
cam_periph_ccbwait(ccb); | cam_periph_ccbwait(ccb); | ||||
else { | |||||
xpt_pollwait(ccb, timeout); | |||||
cem: Maybe name it `pollwait` for consistency with `ccbwait`. To me `poll` alone implies checking… | |||||
timeout = ccb->ccb_h.timeout * 10; | |||||
} | |||||
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) | if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) | ||||
error = 0; | error = 0; | ||||
else if (error_routine != NULL) { | else if (error_routine != NULL) { | ||||
ccb->ccb_h.cbfcnp = cam_periph_done; | ccb->ccb_h.cbfcnp = cam_periph_done; | ||||
error = (*error_routine)(ccb, camflags, sense_flags); | error = (*error_routine)(ccb, camflags, sense_flags); | ||||
} else | } else | ||||
error = 0; | error = 0; | ||||
} while (error == ERESTART); | } while (error == ERESTART); | ||||
} | |||||
if (sched_stopped) | |||||
mtx_lock(periph_mtx); | |||||
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { | if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { | ||||
cam_release_devq(ccb->ccb_h.path, | cam_release_devq(ccb->ccb_h.path, | ||||
/* relsim_flags */0, | /* relsim_flags */0, | ||||
/* openings */0, | /* openings */0, | ||||
/* timeout */0, | /* timeout */0, | ||||
/* getcount_only */ FALSE); | /* getcount_only */ FALSE); | ||||
ccb->ccb_h.status &= ~CAM_DEV_QFRZN; | ccb->ccb_h.status &= ~CAM_DEV_QFRZN; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 824 Lines • Show Last 20 Lines |
Maybe name it pollwait for consistency with ccbwait. To me poll alone implies checking once, rather than the timeout sleep-wait-retry loop xpt_poll implements.