Lines Matching +full:dma +full:- +full:requests

12  * See the COPYING file in the top-level directory.
18 #include "standard-headers/linux/virtio_ids.h"
19 #include "hw/virtio/virtio-scsi.h"
20 #include "migration/qemu-file-types.h"
21 #include "qemu/defer-call.h"
22 #include "qemu/error-report.h"
25 #include "system/block-backend.h"
26 #include "system/dma.h"
27 #include "hw/qdev-properties.h"
30 #include "hw/virtio/iothread-vq-mapping.h"
31 #include "hw/virtio/virtio-bus.h"
32 #include "hw/virtio/virtio-access.h"
38 * - fields up to resp_iov are initialized by virtio_scsi_init_req;
39 * - fields starting at vring are zeroed by virtio_scsi_init_req.
48 /* Used for two-stage request submission and TMFs deferred to BH */
83 return scsi_device_get(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun)); in virtio_scsi_device_get()
90 offsetof(VirtIOSCSIReq, resp_iov) + sizeof(req->resp_iov); in virtio_scsi_init_req()
92 req->vq = vq; in virtio_scsi_init_req()
93 req->dev = s; in virtio_scsi_init_req()
94 qemu_sglist_init(&req->qsgl, DEVICE(s), 8, vdev->dma_as); in virtio_scsi_init_req()
95 qemu_iovec_init(&req->resp_iov, 1); in virtio_scsi_init_req()
96 memset((uint8_t *)req + zero_skip, 0, sizeof(*req) - zero_skip); in virtio_scsi_init_req()
101 qemu_iovec_destroy(&req->resp_iov); in virtio_scsi_free_req()
102 qemu_sglist_destroy(&req->qsgl); in virtio_scsi_free_req()
108 VirtIOSCSI *s = req->dev; in virtio_scsi_complete_req()
109 VirtQueue *vq = req->vq; in virtio_scsi_complete_req()
112 qemu_iovec_from_buf(&req->resp_iov, 0, &req->resp, req->resp_size); in virtio_scsi_complete_req()
118 virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size); in virtio_scsi_complete_req()
119 if (s->dataplane_started && !s->dataplane_fenced) { in virtio_scsi_complete_req()
129 if (req->sreq) { in virtio_scsi_complete_req()
130 req->sreq->hba_private = NULL; in virtio_scsi_complete_req()
131 scsi_req_unref(req->sreq); in virtio_scsi_complete_req()
138 virtio_error(VIRTIO_DEVICE(req->dev), "wrong size for virtio-scsi headers"); in virtio_scsi_bad_req()
144 virtqueue_detach_element(req->vq, &req->elem, 0); in virtio_scsi_bad_req()
156 QEMUSGList *qsgl = &req->qsgl; in qemu_sgl_concat()
160 if (skip >= iov->iov_len) { in qemu_sgl_concat()
161 skip -= iov->iov_len; in qemu_sgl_concat()
163 qemu_sglist_add(qsgl, *addr + skip, iov->iov_len - skip); in qemu_sgl_concat()
164 copied += iov->iov_len - skip; in qemu_sgl_concat()
169 num--; in qemu_sgl_concat()
179 VirtIODevice *vdev = (VirtIODevice *) req->dev; in virtio_scsi_parse_req()
182 if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0, in virtio_scsi_parse_req()
183 &req->req, req_size) < req_size) { in virtio_scsi_parse_req()
184 return -EINVAL; in virtio_scsi_parse_req()
187 if (qemu_iovec_concat_iov(&req->resp_iov, in virtio_scsi_parse_req()
188 req->elem.in_sg, req->elem.in_num, 0, in virtio_scsi_parse_req()
190 return -EINVAL; in virtio_scsi_parse_req()
193 req->resp_size = resp_size; in virtio_scsi_parse_req()
196 * As a workaround, always consider the first buffer as the virtio-scsi in virtio_scsi_parse_req()
200 * The actual length of the response header, stored in req->resp_size, in virtio_scsi_parse_req()
206 if (req->elem.out_num) { in virtio_scsi_parse_req()
207 req_size = req->elem.out_sg[0].iov_len; in virtio_scsi_parse_req()
209 if (req->elem.in_num) { in virtio_scsi_parse_req()
210 resp_size = req->elem.in_sg[0].iov_len; in virtio_scsi_parse_req()
214 out_size = qemu_sgl_concat(req, req->elem.out_sg, in virtio_scsi_parse_req()
215 &req->elem.out_addr[0], req->elem.out_num, in virtio_scsi_parse_req()
217 in_size = qemu_sgl_concat(req, req->elem.in_sg, in virtio_scsi_parse_req()
218 &req->elem.in_addr[0], req->elem.in_num, in virtio_scsi_parse_req()
222 return -ENOTSUP; in virtio_scsi_parse_req()
226 req->mode = SCSI_XFER_TO_DEV; in virtio_scsi_parse_req()
228 req->mode = SCSI_XFER_FROM_DEV; in virtio_scsi_parse_req()
243 req = virtqueue_pop(vq, sizeof(VirtIOSCSIReq) + vs->cdb_size); in virtio_scsi_pop_req()
258 VirtIOSCSIReq *req = sreq->hba_private; in virtio_scsi_save_request()
259 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev); in virtio_scsi_save_request()
260 VirtIODevice *vdev = VIRTIO_DEVICE(req->dev); in virtio_scsi_save_request()
261 uint32_t n = virtio_get_queue_index(req->vq) - VIRTIO_SCSI_VQ_NUM_FIXED; in virtio_scsi_save_request()
263 assert(n < vs->conf.num_queues); in virtio_scsi_save_request()
265 qemu_put_virtqueue_element(vdev, f, &req->elem); in virtio_scsi_save_request()
270 SCSIBus *bus = sreq->bus; in virtio_scsi_load_request()
278 assert(n < vs->conf.num_queues); in virtio_scsi_load_request()
280 sizeof(VirtIOSCSIReq) + vs->cdb_size); in virtio_scsi_load_request()
281 virtio_scsi_init_req(s, vs->cmd_vqs[n], req); in virtio_scsi_load_request()
283 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size, in virtio_scsi_load_request()
284 sizeof(VirtIOSCSICmdResp) + vs->sense_size) < 0) { in virtio_scsi_load_request()
290 req->sreq = sreq; in virtio_scsi_load_request()
291 if (req->sreq->cmd.mode != SCSI_XFER_NONE) { in virtio_scsi_load_request()
292 assert(req->sreq->cmd.mode == req->mode); in virtio_scsi_load_request()
304 if (qatomic_fetch_dec(&tmf->remaining) == 1) { in virtio_scsi_tmf_dec_remaining()
305 trace_virtio_scsi_tmf_resp(virtio_scsi_get_lun(tmf->req.tmf.lun), in virtio_scsi_tmf_dec_remaining()
306 tmf->req.tmf.tag, tmf->resp.tmf.response); in virtio_scsi_tmf_dec_remaining()
308 virtio_scsi_complete_req(tmf, &tmf->dev->ctrl_lock); in virtio_scsi_tmf_dec_remaining()
318 virtio_scsi_tmf_dec_remaining(n->tmf_req); in virtio_scsi_cancel_notify()
326 assert(r->ctx == qemu_get_current_aio_context()); in virtio_scsi_tmf_cancel_req()
329 qatomic_inc(&tmf->remaining); in virtio_scsi_tmf_cancel_req()
332 notifier->notifier.notify = virtio_scsi_cancel_notify; in virtio_scsi_tmf_cancel_req()
333 notifier->tmf_req = tmf; in virtio_scsi_tmf_cancel_req()
334 scsi_req_cancel_async(r, &notifier->notifier); in virtio_scsi_tmf_cancel_req()
337 /* Execute a TMF on the requests in the current AioContext */
342 VirtIOSCSI *s = tmf->dev; in virtio_scsi_do_tmf_aio_context()
343 SCSIDevice *d = virtio_scsi_device_get(s, tmf->req.tmf.lun); in virtio_scsi_do_tmf_aio_context()
348 tmf->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET; in virtio_scsi_do_tmf_aio_context()
358 switch (tmf->req.tmf.subtype) { in virtio_scsi_do_tmf_aio_context()
370 WITH_QEMU_LOCK_GUARD(&d->requests_lock) { in virtio_scsi_do_tmf_aio_context()
371 QTAILQ_FOREACH(r, &d->requests, next) { in virtio_scsi_do_tmf_aio_context()
372 VirtIOSCSIReq *cmd_req = r->hba_private; in virtio_scsi_do_tmf_aio_context()
375 if (r->ctx != ctx) { in virtio_scsi_do_tmf_aio_context()
378 if (match_tag && cmd_req->req.cmd.tag != tmf->req.tmf.tag) { in virtio_scsi_do_tmf_aio_context()
403 assert(!s->dataplane_started); in virtio_scsi_flush_defer_tmf_to_aio_context()
405 for (uint32_t i = 0; i < s->parent_obj.conf.num_queues; i++) { in virtio_scsi_flush_defer_tmf_to_aio_context()
406 AioContext *ctx = s->vq_aio_context[VIRTIO_SCSI_VQ_NUM_FIXED + i]; in virtio_scsi_flush_defer_tmf_to_aio_context()
414 * Run the TMF in a specific AioContext, handling only requests in that
415 * AioContext. This is necessary because requests can run in different
423 qatomic_inc(&tmf->remaining); in virtio_scsi_defer_tmf_to_aio_context()
437 WITH_QEMU_LOCK_GUARD(&d->requests_lock) { in find_aio_context_for_tmf_tag()
441 QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) { in find_aio_context_for_tmf_tag()
442 VirtIOSCSIReq *cmd_req = r->hba_private; in find_aio_context_for_tmf_tag()
444 /* hba_private is non-NULL while the request is enqueued */ in find_aio_context_for_tmf_tag()
447 if (cmd_req->req.cmd.tag == tmf->req.tmf.tag) { in find_aio_context_for_tmf_tag()
448 return r->ctx; in find_aio_context_for_tmf_tag()
456 * -EINPROGRESS if the request is submitted and will be completed later, in the
460 SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun); in virtio_scsi_do_tmf()
466 req->resp.tmf.response = VIRTIO_SCSI_S_OK; in virtio_scsi_do_tmf()
469 * req->req.tmf has the QEMU_PACKED attribute. Don't use virtio_tswap32s() in virtio_scsi_do_tmf()
472 req->req.tmf.subtype = in virtio_scsi_do_tmf()
473 virtio_tswap32(VIRTIO_DEVICE(s), req->req.tmf.subtype); in virtio_scsi_do_tmf()
475 trace_virtio_scsi_tmf_req(virtio_scsi_get_lun(req->req.tmf.lun), in virtio_scsi_do_tmf()
476 req->req.tmf.tag, req->req.tmf.subtype); in virtio_scsi_do_tmf()
478 switch (req->req.tmf.subtype) { in virtio_scsi_do_tmf()
483 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) { in virtio_scsi_do_tmf()
490 ret = -EINPROGRESS; in virtio_scsi_do_tmf()
499 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) { in virtio_scsi_do_tmf()
503 WITH_QEMU_LOCK_GUARD(&d->requests_lock) { in virtio_scsi_do_tmf()
504 QTAILQ_FOREACH(r, &d->requests, next) { in virtio_scsi_do_tmf()
505 VirtIOSCSIReq *cmd_req = r->hba_private; in virtio_scsi_do_tmf()
508 if (cmd_req->req.cmd.tag == req->req.tmf.tag) { in virtio_scsi_do_tmf()
514 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED; in virtio_scsi_do_tmf()
524 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) { in virtio_scsi_do_tmf()
527 qatomic_inc(&s->resetting); in virtio_scsi_do_tmf()
528 device_cold_reset(&d->qdev); in virtio_scsi_do_tmf()
529 qatomic_dec(&s->resetting); in virtio_scsi_do_tmf()
534 int target = req->req.tmf.lun[1]; in virtio_scsi_do_tmf()
535 qatomic_inc(&s->resetting); in virtio_scsi_do_tmf()
538 QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) { in virtio_scsi_do_tmf()
539 SCSIDevice *d1 = SCSI_DEVICE(kid->child); in virtio_scsi_do_tmf()
540 if (d1->channel == 0 && d1->id == target) { in virtio_scsi_do_tmf()
541 device_cold_reset(&d1->qdev); in virtio_scsi_do_tmf()
546 qatomic_dec(&s->resetting); in virtio_scsi_do_tmf()
557 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) { in virtio_scsi_do_tmf()
561 qatomic_inc(&req->remaining); in virtio_scsi_do_tmf()
563 for (uint32_t i = 0; i < s->parent_obj.conf.num_queues; i++) { in virtio_scsi_do_tmf()
564 ctx = s->vq_aio_context[VIRTIO_SCSI_VQ_NUM_FIXED + i]; in virtio_scsi_do_tmf()
574 ret = -EINPROGRESS; in virtio_scsi_do_tmf()
582 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) { in virtio_scsi_do_tmf()
586 WITH_QEMU_LOCK_GUARD(&d->requests_lock) { in virtio_scsi_do_tmf()
587 QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) { in virtio_scsi_do_tmf()
589 assert(r->hba_private); in virtio_scsi_do_tmf()
595 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED; in virtio_scsi_do_tmf()
603 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED; in virtio_scsi_do_tmf()
611 req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN; in virtio_scsi_do_tmf()
616 req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET; in virtio_scsi_do_tmf()
627 if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0, in virtio_scsi_handle_ctrl_req()
629 virtio_scsi_bad_req(req, &s->ctrl_lock); in virtio_scsi_handle_ctrl_req()
637 virtio_scsi_bad_req(req, &s->ctrl_lock); in virtio_scsi_handle_ctrl_req()
647 virtio_scsi_bad_req(req, &s->ctrl_lock); in virtio_scsi_handle_ctrl_req()
650 req->req.an.event_requested = in virtio_scsi_handle_ctrl_req()
651 virtio_tswap32(VIRTIO_DEVICE(s), req->req.an.event_requested); in virtio_scsi_handle_ctrl_req()
652 trace_virtio_scsi_an_req(virtio_scsi_get_lun(req->req.an.lun), in virtio_scsi_handle_ctrl_req()
653 req->req.an.event_requested); in virtio_scsi_handle_ctrl_req()
654 req->resp.an.event_actual = 0; in virtio_scsi_handle_ctrl_req()
655 req->resp.an.response = VIRTIO_SCSI_S_OK; in virtio_scsi_handle_ctrl_req()
660 trace_virtio_scsi_tmf_resp(virtio_scsi_get_lun(req->req.tmf.lun), in virtio_scsi_handle_ctrl_req()
661 req->req.tmf.tag, in virtio_scsi_handle_ctrl_req()
662 req->resp.tmf.response); in virtio_scsi_handle_ctrl_req()
665 trace_virtio_scsi_an_resp(virtio_scsi_get_lun(req->req.an.lun), in virtio_scsi_handle_ctrl_req()
666 req->resp.an.response); in virtio_scsi_handle_ctrl_req()
667 virtio_scsi_complete_req(req, &s->ctrl_lock); in virtio_scsi_handle_ctrl_req()
669 assert(r == -EINPROGRESS); in virtio_scsi_handle_ctrl_req()
677 while ((req = virtio_scsi_pop_req(s, vq, &s->ctrl_lock))) { in virtio_scsi_handle_ctrl_vq()
692 if (s->dataplane_started) { in virtio_scsi_defer_to_dataplane()
695 if (s->vq_aio_context[0] == qemu_get_aio_context()) { in virtio_scsi_defer_to_dataplane()
699 virtio_device_start_ioeventfd(&s->parent_obj.parent_obj); in virtio_scsi_defer_to_dataplane()
700 return !s->dataplane_fenced; in virtio_scsi_defer_to_dataplane()
716 trace_virtio_scsi_cmd_resp(virtio_scsi_get_lun(req->req.cmd.lun), in virtio_scsi_complete_cmd_req()
717 req->req.cmd.tag, in virtio_scsi_complete_cmd_req()
718 req->resp.cmd.response, in virtio_scsi_complete_cmd_req()
719 req->resp.cmd.status); in virtio_scsi_complete_cmd_req()
720 /* Sense data is not in req->resp and is copied separately in virtio_scsi_complete_cmd_req()
723 req->resp_size = sizeof(VirtIOSCSICmdResp); in virtio_scsi_complete_cmd_req()
729 VirtIOSCSIReq *req = r->hba_private; in virtio_scsi_command_failed()
731 if (r->io_canceled) { in virtio_scsi_command_failed()
735 req->resp.cmd.status = GOOD; in virtio_scsi_command_failed()
736 switch (r->host_status) { in virtio_scsi_command_failed()
738 req->resp.cmd.response = VIRTIO_SCSI_S_INCORRECT_LUN; in virtio_scsi_command_failed()
741 req->resp.cmd.response = VIRTIO_SCSI_S_BUSY; in virtio_scsi_command_failed()
745 req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED; in virtio_scsi_command_failed()
748 req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; in virtio_scsi_command_failed()
751 req->resp.cmd.response = VIRTIO_SCSI_S_RESET; in virtio_scsi_command_failed()
754 req->resp.cmd.response = VIRTIO_SCSI_S_TRANSPORT_FAILURE; in virtio_scsi_command_failed()
757 req->resp.cmd.response = VIRTIO_SCSI_S_TARGET_FAILURE; in virtio_scsi_command_failed()
760 req->resp.cmd.response = VIRTIO_SCSI_S_NEXUS_FAILURE; in virtio_scsi_command_failed()
766 req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE; in virtio_scsi_command_failed()
774 VirtIOSCSIReq *req = r->hba_private; in virtio_scsi_command_complete()
777 VirtIODevice *vdev = VIRTIO_DEVICE(req->dev); in virtio_scsi_command_complete()
779 if (r->io_canceled) { in virtio_scsi_command_complete()
783 req->resp.cmd.response = VIRTIO_SCSI_S_OK; in virtio_scsi_command_complete()
784 req->resp.cmd.status = r->status; in virtio_scsi_command_complete()
785 if (req->resp.cmd.status == GOOD) { in virtio_scsi_command_complete()
786 req->resp.cmd.resid = virtio_tswap32(vdev, resid); in virtio_scsi_command_complete()
788 req->resp.cmd.resid = 0; in virtio_scsi_command_complete()
790 sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd)); in virtio_scsi_command_complete()
791 qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd), in virtio_scsi_command_complete()
793 req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len); in virtio_scsi_command_complete()
804 if (cmd->len == 0) { in virtio_scsi_parse_cdb()
805 cmd->len = MIN(VIRTIO_SCSI_CDB_DEFAULT_SIZE, SCSI_CMD_BUF_SIZE); in virtio_scsi_parse_cdb()
806 memcpy(cmd->buf, buf, cmd->len); in virtio_scsi_parse_cdb()
812 cmd->xfer = req->qsgl.size; in virtio_scsi_parse_cdb()
813 cmd->mode = req->mode; in virtio_scsi_parse_cdb()
819 VirtIOSCSIReq *req = r->hba_private; in virtio_scsi_get_sg_list()
821 return &req->qsgl; in virtio_scsi_get_sg_list()
826 VirtIOSCSIReq *req = r->hba_private; in virtio_scsi_request_cancelled()
831 if (qatomic_read(&req->dev->resetting)) { in virtio_scsi_request_cancelled()
832 req->resp.cmd.response = VIRTIO_SCSI_S_RESET; in virtio_scsi_request_cancelled()
834 req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED; in virtio_scsi_request_cancelled()
841 req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE; in virtio_scsi_fail_cmd_req()
851 rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size, in virtio_scsi_handle_cmd_req_prepare()
852 sizeof(VirtIOSCSICmdResp) + vs->sense_size); in virtio_scsi_handle_cmd_req_prepare()
854 if (rc == -ENOTSUP) { in virtio_scsi_handle_cmd_req_prepare()
856 return -ENOTSUP; in virtio_scsi_handle_cmd_req_prepare()
859 return -EINVAL; in virtio_scsi_handle_cmd_req_prepare()
862 trace_virtio_scsi_cmd_req(virtio_scsi_get_lun(req->req.cmd.lun), in virtio_scsi_handle_cmd_req_prepare()
863 req->req.cmd.tag, req->req.cmd.cdb[0]); in virtio_scsi_handle_cmd_req_prepare()
865 d = virtio_scsi_device_get(s, req->req.cmd.lun); in virtio_scsi_handle_cmd_req_prepare()
867 req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; in virtio_scsi_handle_cmd_req_prepare()
869 return -ENOENT; in virtio_scsi_handle_cmd_req_prepare()
871 req->sreq = scsi_req_new(d, req->req.cmd.tag, in virtio_scsi_handle_cmd_req_prepare()
872 virtio_scsi_get_lun(req->req.cmd.lun), in virtio_scsi_handle_cmd_req_prepare()
873 req->req.cmd.cdb, vs->cdb_size, req); in virtio_scsi_handle_cmd_req_prepare()
875 if (req->sreq->cmd.mode != SCSI_XFER_NONE in virtio_scsi_handle_cmd_req_prepare()
876 && (req->sreq->cmd.mode != req->mode || in virtio_scsi_handle_cmd_req_prepare()
877 req->sreq->cmd.xfer > req->qsgl.size)) { in virtio_scsi_handle_cmd_req_prepare()
878 req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN; in virtio_scsi_handle_cmd_req_prepare()
881 return -ENOBUFS; in virtio_scsi_handle_cmd_req_prepare()
883 scsi_req_ref(req->sreq); in virtio_scsi_handle_cmd_req_prepare()
891 SCSIRequest *sreq = req->sreq; in virtio_scsi_handle_cmd_req_submit()
916 } else if (ret == -EINVAL) { in virtio_scsi_handle_cmd_vq()
922 scsi_req_unref(req->sreq); in virtio_scsi_handle_cmd_vq()
923 virtqueue_detach_element(req->vq, &req->elem, 0); in virtio_scsi_handle_cmd_vq()
932 } while (ret != -EINVAL && !virtio_queue_empty(vq)); in virtio_scsi_handle_cmd_vq()
941 /* use non-QOM casts in the data path */ in virtio_scsi_handle_cmd()
957 virtio_stl_p(vdev, &scsiconf->num_queues, s->conf.num_queues); in virtio_scsi_get_config()
958 virtio_stl_p(vdev, &scsiconf->seg_max, in virtio_scsi_get_config()
959 s->conf.seg_max_adjust ? s->conf.virtqueue_size - 2 : 128 - 2); in virtio_scsi_get_config()
960 virtio_stl_p(vdev, &scsiconf->max_sectors, s->conf.max_sectors); in virtio_scsi_get_config()
961 virtio_stl_p(vdev, &scsiconf->cmd_per_lun, s->conf.cmd_per_lun); in virtio_scsi_get_config()
962 virtio_stl_p(vdev, &scsiconf->event_info_size, sizeof(VirtIOSCSIEvent)); in virtio_scsi_get_config()
963 virtio_stl_p(vdev, &scsiconf->sense_size, s->sense_size); in virtio_scsi_get_config()
964 virtio_stl_p(vdev, &scsiconf->cdb_size, s->cdb_size); in virtio_scsi_get_config()
965 virtio_stw_p(vdev, &scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL); in virtio_scsi_get_config()
966 virtio_stw_p(vdev, &scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET); in virtio_scsi_get_config()
967 virtio_stl_p(vdev, &scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN); in virtio_scsi_get_config()
976 if ((uint32_t) virtio_ldl_p(vdev, &scsiconf->sense_size) >= 65536 || in virtio_scsi_set_config()
977 (uint32_t) virtio_ldl_p(vdev, &scsiconf->cdb_size) >= 256) { in virtio_scsi_set_config()
979 "bad data written to virtio-scsi configuration space"); in virtio_scsi_set_config()
983 vs->sense_size = virtio_ldl_p(vdev, &scsiconf->sense_size); in virtio_scsi_set_config()
984 vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size); in virtio_scsi_set_config()
993 /* Firstly sync all virtio-scsi possible supported features */ in virtio_scsi_get_features()
994 requested_features |= s->host_features; in virtio_scsi_get_features()
1003 assert(!s->dataplane_started); in virtio_scsi_reset()
1007 qatomic_inc(&s->resetting); in virtio_scsi_reset()
1008 bus_cold_reset(BUS(&s->bus)); in virtio_scsi_reset()
1009 qatomic_dec(&s->resetting); in virtio_scsi_reset()
1011 vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE; in virtio_scsi_reset()
1012 vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE; in virtio_scsi_reset()
1014 WITH_QEMU_LOCK_GUARD(&s->event_lock) { in virtio_scsi_reset()
1015 s->events_dropped = false; in virtio_scsi_reset()
1038 uint32_t event = info->event; in virtio_scsi_push_event()
1039 uint32_t reason = info->reason; in virtio_scsi_push_event()
1041 if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { in virtio_scsi_push_event()
1045 req = virtio_scsi_pop_req(s, vs->event_vq, &s->event_lock); in virtio_scsi_push_event()
1046 WITH_QEMU_LOCK_GUARD(&s->event_lock) { in virtio_scsi_push_event()
1048 s->events_dropped = true; in virtio_scsi_push_event()
1052 if (s->events_dropped) { in virtio_scsi_push_event()
1054 s->events_dropped = false; in virtio_scsi_push_event()
1059 virtio_scsi_bad_req(req, &s->event_lock); in virtio_scsi_push_event()
1063 evt = &req->resp.event; in virtio_scsi_push_event()
1065 evt->event = virtio_tswap32(vdev, event); in virtio_scsi_push_event()
1066 evt->reason = virtio_tswap32(vdev, reason); in virtio_scsi_push_event()
1068 evt->lun[0] = 1; in virtio_scsi_push_event()
1069 evt->lun[1] = info->address.id; in virtio_scsi_push_event()
1072 if (info->address.lun >= 256) { in virtio_scsi_push_event()
1073 evt->lun[2] = (info->address.lun >> 8) | 0x40; in virtio_scsi_push_event()
1075 evt->lun[3] = info->address.lun & 0xFF; in virtio_scsi_push_event()
1077 trace_virtio_scsi_event(virtio_scsi_get_lun(evt->lun), event, reason); in virtio_scsi_push_event()
1079 virtio_scsi_complete_req(req, &s->event_lock); in virtio_scsi_push_event()
1086 WITH_QEMU_LOCK_GUARD(&s->event_lock) { in virtio_scsi_handle_event_vq()
1087 events_dropped = s->events_dropped; in virtio_scsi_handle_event_vq()
1115 dev->type != TYPE_ROM) { in virtio_scsi_change()
1120 .id = dev->id, in virtio_scsi_change()
1121 .lun = dev->lun, in virtio_scsi_change()
1133 sd->hba_supports_iothread = true; in virtio_scsi_pre_hotplug()
1141 AioContext *ctx = s->vq_aio_context[VIRTIO_SCSI_VQ_NUM_FIXED]; in virtio_scsi_hotplug()
1144 if (ctx != qemu_get_aio_context() && !s->dataplane_fenced) { in virtio_scsi_hotplug()
1150 blk_set_aio_context(sd->conf.blk, ctx, NULL); in virtio_scsi_hotplug()
1158 .id = sd->id, in virtio_scsi_hotplug()
1159 .lun = sd->lun, in virtio_scsi_hotplug()
1164 scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED)); in virtio_scsi_hotplug()
1178 .id = sd->id, in virtio_scsi_hotunplug()
1179 .lun = sd->lun, in virtio_scsi_hotunplug()
1185 if (s->vq_aio_context[VIRTIO_SCSI_VQ_NUM_FIXED] != qemu_get_aio_context()) { in virtio_scsi_hotunplug()
1187 blk_set_aio_context(sd->conf.blk, qemu_get_aio_context(), NULL); in virtio_scsi_hotunplug()
1192 scsi_bus_set_ua(&s->bus, SENSE_CODE(REPORTED_LUNS_CHANGED)); in virtio_scsi_hotunplug()
1202 s->parent_obj.conf.num_queues; in virtio_scsi_drained_begin()
1206 * already been detached. Detaching multiple times is a no-op if nothing in virtio_scsi_drained_begin()
1213 if (s->dataplane_stopping || !s->dataplane_started) { in virtio_scsi_drained_begin()
1219 virtio_queue_aio_detach_host_notifier(vq, s->vq_aio_context[i]); in virtio_scsi_drained_begin()
1230 s->parent_obj.conf.num_queues; in virtio_scsi_drained_end()
1239 if (s->dataplane_stopping || !s->dataplane_started) { in virtio_scsi_drained_end()
1245 AioContext *ctx = s->vq_aio_context[i]; in virtio_scsi_drained_end()
1247 if (vq == vs->event_vq) { in virtio_scsi_drained_end()
1285 if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { in virtio_scsi_common_realize()
1286 s->conf.num_queues = 1; in virtio_scsi_common_realize()
1288 if (s->conf.num_queues == 0 || in virtio_scsi_common_realize()
1289 s->conf.num_queues > VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED) { in virtio_scsi_common_realize()
1292 s->conf.num_queues, in virtio_scsi_common_realize()
1293 VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED); in virtio_scsi_common_realize()
1297 if (s->conf.virtqueue_size <= 2) { in virtio_scsi_common_realize()
1299 "must be > 2", s->conf.virtqueue_size); in virtio_scsi_common_realize()
1302 s->cmd_vqs = g_new0(VirtQueue *, s->conf.num_queues); in virtio_scsi_common_realize()
1303 s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE; in virtio_scsi_common_realize()
1304 s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE; in virtio_scsi_common_realize()
1306 s->ctrl_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, ctrl); in virtio_scsi_common_realize()
1307 s->event_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, evt); in virtio_scsi_common_realize()
1308 for (i = 0; i < s->conf.num_queues; i++) { in virtio_scsi_common_realize()
1309 s->cmd_vqs[i] = virtio_add_queue(vdev, s->conf.virtqueue_size, cmd); in virtio_scsi_common_realize()
1319 qemu_mutex_init(&s->ctrl_lock); in virtio_scsi_device_realize()
1320 qemu_mutex_init(&s->event_lock); in virtio_scsi_device_realize()
1332 scsi_bus_init_named(&s->bus, sizeof(s->bus), dev, in virtio_scsi_device_realize()
1333 &virtio_scsi_scsi_info, vdev->bus_name); in virtio_scsi_device_realize()
1334 /* override default SCSI bus hotplug-handler, with virtio-scsi's one */ in virtio_scsi_device_realize()
1335 qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev)); in virtio_scsi_device_realize()
1346 virtio_delete_queue(vs->ctrl_vq); in virtio_scsi_common_unrealize()
1347 virtio_delete_queue(vs->event_vq); in virtio_scsi_common_unrealize()
1348 for (i = 0; i < vs->conf.num_queues; i++) { in virtio_scsi_common_unrealize()
1349 virtio_delete_queue(vs->cmd_vqs[i]); in virtio_scsi_common_unrealize()
1351 g_free(vs->cmd_vqs); in virtio_scsi_common_unrealize()
1361 qbus_set_hotplug_handler(BUS(&s->bus), NULL); in virtio_scsi_device_unrealize()
1363 qemu_mutex_destroy(&s->event_lock); in virtio_scsi_device_unrealize()
1364 qemu_mutex_destroy(&s->ctrl_lock); in virtio_scsi_device_unrealize()
1384 DEFINE_PROP_IOTHREAD_VQ_MAPPING_LIST("iothread-vq-mapping", VirtIOSCSI,
1389 .name = "virtio-scsi",
1403 vdc->get_config = virtio_scsi_get_config; in virtio_scsi_common_class_init()
1404 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); in virtio_scsi_common_class_init()
1414 dc->vmsd = &vmstate_virtio_scsi; in virtio_scsi_class_init()
1415 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); in virtio_scsi_class_init()
1416 vdc->realize = virtio_scsi_device_realize; in virtio_scsi_class_init()
1417 vdc->unrealize = virtio_scsi_device_unrealize; in virtio_scsi_class_init()
1418 vdc->set_config = virtio_scsi_set_config; in virtio_scsi_class_init()
1419 vdc->get_features = virtio_scsi_get_features; in virtio_scsi_class_init()
1420 vdc->reset = virtio_scsi_reset; in virtio_scsi_class_init()
1421 vdc->start_ioeventfd = virtio_scsi_dataplane_start; in virtio_scsi_class_init()
1422 vdc->stop_ioeventfd = virtio_scsi_dataplane_stop; in virtio_scsi_class_init()
1423 hc->pre_plug = virtio_scsi_pre_hotplug; in virtio_scsi_class_init()
1424 hc->plug = virtio_scsi_hotplug; in virtio_scsi_class_init()
1425 hc->unplug = virtio_scsi_hotunplug; in virtio_scsi_class_init()