Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/virtio/scsi/virtio_scsi.c
Show First 20 Lines • Show All 280 Lines • ▼ Show 20 Lines | vtscsi_attach(device_t dev) | ||||
int error; | int error; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->vtscsi_dev = dev; | sc->vtscsi_dev = dev; | ||||
virtio_set_feature_desc(dev, vtscsi_feature_desc); | virtio_set_feature_desc(dev, vtscsi_feature_desc); | ||||
VTSCSI_LOCK_INIT(sc, device_get_nameunit(dev)); | VTSCSI_LOCK_INIT(sc, device_get_nameunit(dev)); | ||||
TAILQ_INIT(&sc->vtscsi_req_free); | TAILQ_INIT(&sc->vtscsi_req_free); | ||||
TAILQ_INIT(&sc->vtscsi_resrc_pend); | |||||
vtscsi_get_tunables(sc); | vtscsi_get_tunables(sc); | ||||
vtscsi_setup_sysctl(sc); | vtscsi_setup_sysctl(sc); | ||||
error = vtscsi_setup_features(sc); | error = vtscsi_setup_features(sc); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, "cannot setup features\n"); | device_printf(dev, "cannot setup features\n"); | ||||
goto fail; | goto fail; | ||||
▲ Show 20 Lines • Show All 449 Lines • ▼ Show 20 Lines | if (sc->vtscsi_flags & VTSCSI_FLAG_DETACH) { | ||||
*/ | */ | ||||
ccbh->status = CAM_NO_HBA; | ccbh->status = CAM_NO_HBA; | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
return; | return; | ||||
} | } | ||||
switch (ccbh->func_code) { | switch (ccbh->func_code) { | ||||
case XPT_SCSI_IO: | case XPT_SCSI_IO: | ||||
if (!TAILQ_EMPTY(&sc->vtscsi_resrc_pend)) | |||||
TAILQ_INSERT_TAIL(&sc->vtscsi_resrc_pend, ccbh, sim_links.tqe); | |||||
else | |||||
vtscsi_cam_scsi_io(sc, sim, ccb); | vtscsi_cam_scsi_io(sc, sim, ccb); | ||||
break; | break; | ||||
case XPT_SET_TRAN_SETTINGS: | case XPT_SET_TRAN_SETTINGS: | ||||
ccbh->status = CAM_FUNC_NOTAVAIL; | ccbh->status = CAM_FUNC_NOTAVAIL; | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
break; | break; | ||||
case XPT_GET_TRAN_SETTINGS: | case XPT_GET_TRAN_SETTINGS: | ||||
▲ Show 20 Lines • Show All 361 Lines • ▼ Show 20 Lines | vtscsi_execute_scsi_cmd(struct vtscsi_softc *sc, struct vtscsi_request *req) | ||||
req->vsr_complete = vtscsi_complete_scsi_cmd; | req->vsr_complete = vtscsi_complete_scsi_cmd; | ||||
cmd_resp->response = -1; | cmd_resp->response = -1; | ||||
error = virtqueue_enqueue(vq, req, sg, readable, writable); | error = virtqueue_enqueue(vq, req, sg, readable, writable); | ||||
if (error) { | if (error) { | ||||
vtscsi_dprintf(sc, VTSCSI_ERROR, | vtscsi_dprintf(sc, VTSCSI_ERROR, | ||||
"enqueue error=%d req=%p ccb=%p\n", error, req, ccbh); | "enqueue error=%d req=%p ccb=%p\n", error, req, ccbh); | ||||
ccbh->sim_priv.entries[0].field = (readable + writable); | |||||
ccbh->status = CAM_REQUEUE_REQ; | vtscsi_enqueue_request(sc, req); | ||||
vtscsi_freeze_simq(sc, VTSCSI_REQUEST_VQ); | TAILQ_INSERT_TAIL(&sc->vtscsi_resrc_pend, ccbh, sim_links.tqe); | ||||
return (error); | sc->vtscsi_stats.num_pends++; | ||||
return 0; | |||||
} | } | ||||
ccbh->status |= CAM_SIM_QUEUED; | ccbh->status |= CAM_SIM_QUEUED; | ||||
ccbh->ccbh_vtscsi_req = req; | ccbh->ccbh_vtscsi_req = req; | ||||
virtqueue_notify(vq); | virtqueue_notify(vq); | ||||
if (ccbh->timeout != CAM_TIME_INFINITY) { | if (ccbh->timeout != CAM_TIME_INFINITY) { | ||||
▲ Show 20 Lines • Show All 234 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
vtscsi_complete_scsi_cmd(struct vtscsi_softc *sc, struct vtscsi_request *req) | vtscsi_complete_scsi_cmd(struct vtscsi_softc *sc, struct vtscsi_request *req) | ||||
{ | { | ||||
struct ccb_hdr *ccbh; | struct ccb_hdr *ccbh; | ||||
struct ccb_scsiio *csio; | struct ccb_scsiio *csio; | ||||
struct virtio_scsi_cmd_resp *cmd_resp; | struct virtio_scsi_cmd_resp *cmd_resp; | ||||
cam_status status; | cam_status status; | ||||
uint16_t nfree; | |||||
csio = &req->vsr_ccb->csio; | csio = &req->vsr_ccb->csio; | ||||
ccbh = &csio->ccb_h; | ccbh = &csio->ccb_h; | ||||
cmd_resp = &req->vsr_cmd_resp; | cmd_resp = &req->vsr_cmd_resp; | ||||
KASSERT(ccbh->ccbh_vtscsi_req == req, | KASSERT(ccbh->ccbh_vtscsi_req == req, | ||||
("ccb %p req mismatch %p/%p", ccbh, ccbh->ccbh_vtscsi_req, req)); | ("ccb %p req mismatch %p/%p", ccbh, ccbh->ccbh_vtscsi_req, req)); | ||||
Show All 16 Lines | if (vtscsi_thaw_simq(sc, VTSCSI_REQUEST | VTSCSI_REQUEST_VQ) != 0) | ||||
status |= CAM_RELEASE_SIMQ; | status |= CAM_RELEASE_SIMQ; | ||||
vtscsi_dprintf(sc, VTSCSI_TRACE, "req=%p ccb=%p status=%#x\n", | vtscsi_dprintf(sc, VTSCSI_TRACE, "req=%p ccb=%p status=%#x\n", | ||||
req, ccbh, status); | req, ccbh, status); | ||||
ccbh->status = status; | ccbh->status = status; | ||||
xpt_done(req->vsr_ccb); | xpt_done(req->vsr_ccb); | ||||
vtscsi_enqueue_request(sc, req); | vtscsi_enqueue_request(sc, req); | ||||
while (!TAILQ_EMPTY(&sc->vtscsi_resrc_pend)) { | |||||
ccbh = TAILQ_FIRST(&sc->vtscsi_resrc_pend); | |||||
nfree = virtqueue_nfree(sc->vtscsi_request_vq); | |||||
if (nfree >= ccbh->sim_priv.entries[0].field) { | |||||
TAILQ_REMOVE(&sc->vtscsi_resrc_pend, ccbh, sim_links.tqe); | |||||
vtscsi_cam_scsi_io(sc, sc->vtscsi_sim, (union ccb *)ccbh); | |||||
} else | |||||
/* Can't satisfy the request. */ | |||||
break; | |||||
} | } | ||||
} | |||||
static void | static void | ||||
vtscsi_poll_ctrl_req(struct vtscsi_softc *sc, struct vtscsi_request *req) | vtscsi_poll_ctrl_req(struct vtscsi_softc *sc, struct vtscsi_request *req) | ||||
{ | { | ||||
/* XXX We probably shouldn't poll forever. */ | /* XXX We probably shouldn't poll forever. */ | ||||
req->vsr_flags |= VTSCSI_REQ_FLAG_POLLED; | req->vsr_flags |= VTSCSI_REQ_FLAG_POLLED; | ||||
do | do | ||||
▲ Show 20 Lines • Show All 897 Lines • ▼ Show 20 Lines | SYSCTL_ADD_INT(ctx, child, OID_AUTO, "debug_level", | ||||
"Debug level"); | "Debug level"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "scsi_cmd_timeouts", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "scsi_cmd_timeouts", | ||||
CTLFLAG_RD, &stats->scsi_cmd_timeouts, | CTLFLAG_RD, &stats->scsi_cmd_timeouts, | ||||
"SCSI command timeouts"); | "SCSI command timeouts"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dequeue_no_requests", | SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dequeue_no_requests", | ||||
CTLFLAG_RD, &stats->dequeue_no_requests, | CTLFLAG_RD, &stats->dequeue_no_requests, | ||||
"No available requests to dequeue"); | "No available requests to dequeue"); | ||||
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "num_pends", CTLFLAG_RD, | |||||
&stats->num_pends, "SCSI commands pended"); | |||||
} | } | ||||
static void | static void | ||||
vtscsi_printf_req(struct vtscsi_request *req, const char *func, | vtscsi_printf_req(struct vtscsi_request *req, const char *func, | ||||
const char *fmt, ...) | const char *fmt, ...) | ||||
{ | { | ||||
struct vtscsi_softc *sc; | struct vtscsi_softc *sc; | ||||
union ccb *ccb; | union ccb *ccb; | ||||
Show All 34 Lines |