get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/15792/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 15792,
    "url": "http://patches.dpdk.org/api/patches/15792/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1473899298-4580-2-git-send-email-changpeng.liu@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1473899298-4580-2-git-send-email-changpeng.liu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1473899298-4580-2-git-send-email-changpeng.liu@intel.com",
    "date": "2016-09-15T00:28:18",
    "name": "[dpdk-dev,v2,2/2] vhost: add vhost-scsi support to vhost library",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d35aa069c7661a4f4050129fde7c06a0e9ac4cb8",
    "submitter": {
        "id": 565,
        "url": "http://patches.dpdk.org/api/people/565/?format=api",
        "name": "Liu, Changpeng",
        "email": "changpeng.liu@intel.com"
    },
    "delegate": {
        "id": 355,
        "url": "http://patches.dpdk.org/api/users/355/?format=api",
        "username": "yliu",
        "first_name": "Yuanhan",
        "last_name": "Liu",
        "email": "yuanhan.liu@linux.intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1473899298-4580-2-git-send-email-changpeng.liu@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/15792/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/15792/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id E171E7F2D;\n\tWed, 14 Sep 2016 02:20:26 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id BA93F72FB\n\tfor <dev@dpdk.org>; Wed, 14 Sep 2016 02:20:21 +0200 (CEST)",
            "from fmsmga006.fm.intel.com ([10.253.24.20])\n\tby fmsmga103.fm.intel.com with ESMTP; 13 Sep 2016 17:20:20 -0700",
            "from fedora.sh.intel.com ([10.239.67.161])\n\tby fmsmga006.fm.intel.com with ESMTP; 13 Sep 2016 17:20:18 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.30,331,1470726000\"; d=\"scan'208\";a=\"8082918\"",
        "From": "Changpeng Liu <changpeng.liu@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "yuanhan.liu@intel.com,\n\tjames.r.harris@intel.com",
        "Date": "Thu, 15 Sep 2016 08:28:18 +0800",
        "Message-Id": "<1473899298-4580-2-git-send-email-changpeng.liu@intel.com>",
        "X-Mailer": "git-send-email 1.9.3",
        "In-Reply-To": "<1473899298-4580-1-git-send-email-changpeng.liu@intel.com>",
        "References": "<1473855300-3066-1-git-send-email-changpeng.liu@intel.com>\n\t<1473899298-4580-1-git-send-email-changpeng.liu@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2 2/2] vhost: add vhost-scsi support to vhost\n\tlibrary",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Since we changed the vhost library as a common framework to add other\nVIRTIO device type, here we add VIRTIO_ID_SCSI device type to vhost\nlibrary to support vhost-scsi target.\n\nSigned-off-by: Changpeng Liu <changpeng.liu@intel.com>\n---\n lib/librte_vhost/Makefile          |   4 +-\n lib/librte_vhost/rte_virtio_dev.h  |   1 +\n lib/librte_vhost/rte_virtio_scsi.h |  68 +++++++\n lib/librte_vhost/socket.c          |   2 +\n lib/librte_vhost/vhost_device.h    |   3 +\n lib/librte_vhost/vhost_net.c       |   2 +-\n lib/librte_vhost/vhost_scsi.c      | 354 +++++++++++++++++++++++++++++++++++++\n lib/librte_vhost/vhost_scsi.h      |  68 +++++++\n lib/librte_vhost/vhost_user.c      |  31 +++-\n lib/librte_vhost/vhost_user.h      |   5 +\n lib/librte_vhost/virtio_scsi.c     | 145 +++++++++++++++\n 11 files changed, 675 insertions(+), 8 deletions(-)\n create mode 100644 lib/librte_vhost/rte_virtio_scsi.h\n create mode 100644 lib/librte_vhost/vhost_scsi.c\n create mode 100644 lib/librte_vhost/vhost_scsi.h\n create mode 100644 lib/librte_vhost/virtio_scsi.c",
    "diff": "diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile\nindex af30491..e8fca35 100644\n--- a/lib/librte_vhost/Makefile\n+++ b/lib/librte_vhost/Makefile\n@@ -48,10 +48,10 @@ endif\n \n # all source are stored in SRCS-y\n SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := fd_man.c socket.c vhost_net.c vhost_user.c \\\n-\t\t\t\t   virtio_net.c\n+\t\t\t\t   virtio_net.c vhost_scsi.c virtio_scsi.c\n \n # install includes\n-SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h rte_virtio_dev.h\n+SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h rte_virtio_scsi.h rte_virtio_dev.h\n \n # dependencies\n DEPDIRS-$(CONFIG_RTE_LIBRTE_VHOST) += lib/librte_eal\ndiff --git a/lib/librte_vhost/rte_virtio_dev.h b/lib/librte_vhost/rte_virtio_dev.h\nindex e3c857a..325a208 100644\n--- a/lib/librte_vhost/rte_virtio_dev.h\n+++ b/lib/librte_vhost/rte_virtio_dev.h\n@@ -40,6 +40,7 @@\n #define RTE_VHOST_USER_TX_ZERO_COPY\t(1ULL << 2)\n \n #define RTE_VHOST_USER_DEV_NET\t\t(1ULL << 32)\n+#define RTE_VHOST_USER_DEV_SCSI\t\t(1ULL << 33)\n \n /**\n  * Device and vring operations.\ndiff --git a/lib/librte_vhost/rte_virtio_scsi.h b/lib/librte_vhost/rte_virtio_scsi.h\nnew file mode 100644\nindex 0000000..4e4cec5\n--- /dev/null\n+++ b/lib/librte_vhost/rte_virtio_scsi.h\n@@ -0,0 +1,68 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef _VIRTIO_SCSI_H_\n+#define _VIRTIO_SCSI_H_\n+\n+/**\n+ * @file\n+ * Interface to vhost net\n+ */\n+\n+#include <stdint.h>\n+#include <linux/vhost.h>\n+#include <linux/virtio_ring.h>\n+#include <linux/virtio_scsi.h>\n+#include <sys/eventfd.h>\n+#include <sys/socket.h>\n+\n+#include <rte_memory.h>\n+#include <rte_mempool.h>\n+#include <rte_virtio_dev.h>\n+\n+enum {DIR_DMA_NONE, DIR_DMA_FROM_DEV, DIR_DMA_TO_DEV};\n+\n+/* Register callbacks. */\n+int rte_vhost_scsi_driver_callback_register(struct virtio_net_device_ops const * const);\n+\n+int rte_vhost_scsi_pop_request(int vid, uint16_t queue_id,\n+\tstruct virtio_scsi_cmd_req **request,\n+\tstruct virtio_scsi_cmd_resp **response,\n+\tstruct iovec *iovs, int *iov_cnt, uint32_t *desc_idx,\n+\tuint32_t *xfer_direction);\n+\n+int rte_vhost_scsi_push_response(int vid, uint16_t queue_id,\n+\t\t\t\t uint32_t req_idx, uint32_t len);\n+\n+\n+#endif /* _VIRTIO_SCSI_H_ */\n\\ No newline at end of file\ndiff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c\nindex 1474c98..2b3f854 100644\n--- a/lib/librte_vhost/socket.c\n+++ b/lib/librte_vhost/socket.c\n@@ -527,6 +527,8 @@ rte_vhost_driver_register(const char *path, uint64_t flags)\n \t}\n \n \tvsocket->type = VIRTIO_ID_NET;\n+\tif (flags & RTE_VHOST_USER_DEV_SCSI)\n+\t\tvsocket->type = VIRTIO_ID_SCSI;\n \tvhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;\n \n out:\ndiff --git a/lib/librte_vhost/vhost_device.h b/lib/librte_vhost/vhost_device.h\nindex 7101bb0..f1125e1 100644\n--- a/lib/librte_vhost/vhost_device.h\n+++ b/lib/librte_vhost/vhost_device.h\n@@ -37,6 +37,7 @@\n #include <linux/virtio_ids.h>\n \n #include \"vhost_net.h\"\n+#include \"vhost_scsi.h\"\n #include \"vhost_user.h\"\n \n /* Used to indicate that the device is running on a data core */\n@@ -109,6 +110,7 @@ struct virtio_dev {\n \tuint32_t\t\tdev_type;\n \tunion {\n \t\tstruct virtio_net\tnet_dev;\n+\t\tstruct virtio_scsi\tscsi_dev;\n \t} dev;\n \n \tuint32_t\t\tnr_guest_pages;\n@@ -120,6 +122,7 @@ struct virtio_dev {\n } __rte_cache_aligned;\n \n extern struct virtio_net_device_ops const *notify_ops;\n+extern struct virtio_net_device_ops const *scsi_notify_ops;\n \n /*\n  * Define virtio 1.0 for older kernels\ndiff --git a/lib/librte_vhost/vhost_net.c b/lib/librte_vhost/vhost_net.c\nindex f141b32..e38e3ac 100644\n--- a/lib/librte_vhost/vhost_net.c\n+++ b/lib/librte_vhost/vhost_net.c\n@@ -518,7 +518,7 @@ vhost_net_device_init(struct virtio_dev *device)\n \n \tdevice->fn_table.vhost_dev_ready  = vhost_dev_is_ready;\n \tdevice->fn_table.vhost_dev_get_queues  = vhost_dev_get_queues;\n-\tdevice->fn_table.vhost_dev_cleanup = cleanup_device;\n+\tdevice->fn_table.vhost_dev_cleanup  = cleanup_device;\n \tdevice->fn_table.vhost_dev_free  = free_device;\n \tdevice->fn_table.vhost_dev_reset  = reset_device;\n \tdevice->fn_table.vhost_dev_get_features  = vhost_dev_get_features;\ndiff --git a/lib/librte_vhost/vhost_scsi.c b/lib/librte_vhost/vhost_scsi.c\nnew file mode 100644\nindex 0000000..0f14f77\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_scsi.c\n@@ -0,0 +1,354 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <linux/vhost.h>\n+#include <linux/virtio_scsi.h>\n+#include <stddef.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <assert.h>\n+#include <sys/mman.h>\n+#include <unistd.h>\n+\n+#include <rte_log.h>\n+#include <rte_string_fns.h>\n+#include <rte_memory.h>\n+#include <rte_malloc.h>\n+\n+#include \"vhost_scsi.h\"\n+#include \"vhost_device.h\"\n+\n+/* device ops to add/remove device to/from data core. */\n+struct virtio_net_device_ops const *scsi_notify_ops;\n+\n+/* Features supported by this lib. */\n+#define VHOST_SCSI_SUPPORTED_FEATURES ((1ULL << VIRTIO_SCSI_F_INOUT) | \\\n+\t\t\t\t(1ULL << VIRTIO_SCSI_F_HOTPLUG) | \\\n+\t\t\t\t(1ULL << VIRTIO_SCSI_F_CHANGE))\n+\n+static uint64_t VHOST_SCSI_FEATURES = VHOST_SCSI_SUPPORTED_FEATURES;\n+\n+struct virtio_scsi *\n+get_scsi_device(struct virtio_dev *dev)\n+{\n+\tif (!dev)\n+\t\treturn NULL;\n+ \n+\treturn &dev->dev.scsi_dev;\n+}\n+\n+static void\n+cleanup_vq(struct vhost_virtqueue *vq, int destroy)\n+{\n+\tif ((vq->callfd >= 0) && (destroy != 0))\n+\t\tclose(vq->callfd);\n+\tif (vq->kickfd >= 0)\n+\t\tclose(vq->kickfd);\n+}\n+\n+/*\n+ * Unmap any memory, close any file descriptors and\n+ * free any memory owned by a device.\n+ */\n+static void\n+cleanup_device(struct virtio_dev *device, int destroy)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\tuint32_t i;\n+\n+\tdev->features = 0;\n+\tdev->protocol_features = 0;\n+\n+\tfor (i = 0; i < dev->virt_q_nb; i++) {\n+\t\tcleanup_vq(dev->virtqueue[i], destroy);\n+\t}\n+}\n+\n+static void\n+init_vring_queue(struct vhost_virtqueue *vq)\n+{\n+\tmemset(vq, 0, sizeof(struct vhost_virtqueue));\n+\n+\tvq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD;\n+\tvq->callfd = VIRTIO_UNINITIALIZED_EVENTFD;\n+\n+\t/* Backends are set to -1 indicating an inactive device. */\n+\tvq->backend = -1;\n+\tvq->enabled = 1;\n+}\n+\n+static void\n+reset_vring_queue(struct vhost_virtqueue *vq)\n+{\n+\tint callfd;\n+\n+\tcallfd = vq->callfd;\n+\tinit_vring_queue(vq);\n+\tvq->callfd = callfd;\n+}\n+\n+static int\n+alloc_vring_queue(struct virtio_scsi *dev, uint32_t q_idx)\n+{\n+\tstruct vhost_virtqueue *virtqueue = NULL;\n+\n+\tvirtqueue = rte_malloc(NULL,\n+\t\t\t       sizeof(struct vhost_virtqueue), 0);\n+\tif (virtqueue == NULL) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\"Failed to allocate memory for virt qp:%d.\\n\", q_idx);\n+\t\treturn -1;\n+\t}\n+\n+\tdev->virtqueue[q_idx] = virtqueue;\n+\n+\tinit_vring_queue(virtqueue);\n+\n+\tdev->virt_q_nb += 1;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Reset some variables in device structure, while keeping few\n+ * others untouched, such as vid, ifname, virt_qp_nb: they\n+ * should be same unless the device is removed.\n+ */\n+static void\n+reset_device(struct virtio_dev *device)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < dev->virt_q_nb; i++)\n+\t\treset_vring_queue(dev->virtqueue[i]);\n+}\n+\n+/*\n+ * Release virtqueues and device memory.\n+ */\n+static void\n+free_device(struct virtio_dev *device)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < dev->virt_q_nb; i++)\n+\t\trte_free(dev->virtqueue[i]);\n+\n+\trte_free(dev);\n+}\n+\n+static uint64_t\n+vhost_dev_get_features(struct virtio_dev *dev)\n+{\n+\tif (dev == NULL)\n+\t\treturn 0;\n+\n+\treturn VHOST_SCSI_FEATURES;\t\n+}\n+\n+static int\n+vhost_dev_set_features(struct virtio_dev *device, uint64_t features)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\n+\tif (features & ~VHOST_SCSI_FEATURES)\n+\t\treturn -1;\n+\n+\tdev->features = features;\n+\tLOG_DEBUG(VHOST_CONFIG,\n+\t\t\"(%d) RW %s, Hotplug %s, Status Change %s\\n\",\n+\t\tdevice->vid,\n+\t\t(dev->features & (1ULL << VIRTIO_SCSI_F_INOUT)) ? \"on\" : \"off\",\n+\t\t(dev->features & (1ULL << VIRTIO_SCSI_F_HOTPLUG)) ? \"on\" : \"off\",\n+\t\t(dev->features & (1ULL << VIRTIO_SCSI_F_CHANGE)) ? \"on\" : \"off\");\n+\n+\treturn 0;\n+}\n+\n+static int\n+vq_is_ready(struct vhost_virtqueue *vq)\n+{\n+\treturn vq && vq->desc   &&\n+\t       vq->kickfd != VIRTIO_UNINITIALIZED_EVENTFD &&\n+\t       vq->callfd != VIRTIO_UNINITIALIZED_EVENTFD;\n+}\n+\n+static int\n+vhost_dev_is_ready(struct virtio_dev *device)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\tstruct vhost_virtqueue *vq;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < dev->virt_q_nb; i++) {\n+\t\tvq = dev->virtqueue[i];\n+\n+\t\tif (!vq_is_ready(vq)) {\n+\t\t\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\t\t\"virtio is not ready for processing.\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\"virtio is now ready for processing.\\n\");\n+\treturn 1;\n+}\n+\n+static int\n+vhost_dev_set_vring_call(struct virtio_dev *device, struct vhost_vring_file *file)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\tstruct vhost_virtqueue *vq;\n+\tuint32_t cur_q_idx;\n+\n+\t/*\n+\t * FIXME: VHOST_SET_VRING_CALL is the first per-vring message\n+\t * we get, so we do vring queue pair allocation here.\n+\t */\n+\tcur_q_idx = file->index;\n+\tif (cur_q_idx + 1 > dev->virt_q_nb) {\n+\t\tif (alloc_vring_queue(dev, cur_q_idx) < 0)\n+\t\t\treturn -1;\n+\t}\n+\n+\tvq = dev->virtqueue[file->index];\n+\tassert(vq != NULL);\n+\n+\tif (vq->callfd >= 0)\n+\t\tclose(vq->callfd);\n+\n+\tvq->callfd = file->fd;\n+\treturn 0;\n+}\n+\n+static uint32_t\n+vhost_dev_get_default_queue_num(struct virtio_dev *dev)\n+{\n+\tif (dev == NULL)\n+\t\treturn 0;\n+\n+\treturn VHOST_MAX_SCSI_QUEUES;\n+}\n+\n+static uint32_t\n+vhost_dev_get_queue_num(struct virtio_dev *device)\n+{\n+\tstruct virtio_scsi *dev;\n+\tif (device == NULL)\n+\t\treturn 0;\n+\n+\tdev = get_scsi_device(device);\n+\treturn dev->virt_q_nb;\n+}\n+\n+static int\n+vhost_dev_get_vring_base(struct virtio_dev *device, struct vhost_virtqueue *vq)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\n+\tif (dev == NULL)\n+\t\treturn 0;\n+\t/*\n+\t * Based on current qemu vhost-user implementation, this message is\n+\t * sent and only sent in vhost_vring_stop.\n+\t * TODO: cleanup the vring, it isn't usable since here.\n+\t */\n+\tif (vq->kickfd >= 0)\n+\t\tclose(vq->kickfd);\n+\tvq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD;\n+\n+\tif (vq->callfd >= 0)\n+\t\tclose(vq->callfd);\n+\tvq->callfd = VIRTIO_UNINITIALIZED_EVENTFD;\n+\n+\treturn 0;\n+}\n+\n+static struct vhost_virtqueue *\n+vhost_dev_get_queues(struct virtio_dev *device, uint16_t queue_id)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\tstruct vhost_virtqueue *vq;\n+\n+\tvq = dev->virtqueue[queue_id];\n+\n+\treturn vq;\n+}\n+\n+int\n+vhost_user_scsi_set_endpoint(struct virtio_dev *device, struct VhostUserMsg *pmsg)\n+{\n+       struct virtio_scsi *dev = get_scsi_device(device);\n+\n+       if (!dev || pmsg->size != sizeof(dev->scsi_target))\n+               return -1;\n+\n+       memcpy(&dev->scsi_target, &pmsg->payload.scsi_target, sizeof(dev->scsi_target));\n+\n+       return 0;\n+}\n+\n+void\n+vhost_scsi_device_init(struct virtio_dev *device)\n+{\n+\tstruct virtio_scsi *dev = get_scsi_device(device);\n+\n+\tdevice->fn_table.vhost_dev_ready  = vhost_dev_is_ready;\n+\tdevice->fn_table.vhost_dev_get_queues  = vhost_dev_get_queues;\n+\tdevice->fn_table.vhost_dev_cleanup  = cleanup_device;\n+\tdevice->fn_table.vhost_dev_free  = free_device;\n+\tdevice->fn_table.vhost_dev_reset  = reset_device;\n+\tdevice->fn_table.vhost_dev_get_features  = vhost_dev_get_features;\n+\tdevice->fn_table.vhost_dev_set_features  = vhost_dev_set_features;\n+\tdevice->fn_table.vhost_dev_get_default_queue_num  = vhost_dev_get_default_queue_num;\n+\tdevice->fn_table.vhost_dev_get_queue_num  = vhost_dev_get_queue_num;\n+\tdevice->fn_table.vhost_dev_get_vring_base  = vhost_dev_get_vring_base;\n+\tdevice->fn_table.vhost_dev_set_vring_call  = vhost_dev_set_vring_call;\n+\n+\tdev->device = device;\n+}\n+\n+\n+/*\n+ * Register ops so that we can add/remove device to data core.\n+ */\n+int\n+rte_vhost_scsi_driver_callback_register(struct virtio_net_device_ops const * const ops)\n+{\n+\tscsi_notify_ops = ops;\n+\n+\treturn 0;\n+}\n\\ No newline at end of file\ndiff --git a/lib/librte_vhost/vhost_scsi.h b/lib/librte_vhost/vhost_scsi.h\nnew file mode 100644\nindex 0000000..4aba9b4\n--- /dev/null\n+++ b/lib/librte_vhost/vhost_scsi.h\n@@ -0,0 +1,68 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef _VHOST_SCSI_H_\n+#define _VHOST_SCSI_H_\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <sys/types.h>\n+#include <unistd.h>\n+#include <linux/vhost.h>\n+\n+#include <rte_log.h>\n+\n+#include \"rte_virtio_scsi.h\"\n+#include \"vhost_user.h\"\n+\n+#define VHOST_MAX_SCSI_QUEUES\t\t0x1\n+\n+#define VHOST_USER_SCSI_ABI_VERSION\t0x1\n+\n+/**\n+ * Device structure contains all configuration information relating\n+ * to the device.\n+ */\n+struct virtio_scsi {\n+\tuint64_t\t\tfeatures;\n+\tuint64_t\t\tprotocol_features;\n+\tuint32_t\t\tvirt_q_nb;\n+\tstruct vhost_scsi_target scsi_target;\n+\tstruct vhost_virtqueue\t*virtqueue[VHOST_MAX_SCSI_QUEUES + 2];\n+\tstruct virtio_dev\t*device;\n+} __rte_cache_aligned;\n+\n+struct virtio_scsi *get_scsi_device(struct virtio_dev *dev);\n+void vhost_scsi_device_init(struct virtio_dev *device);\n+int vhost_user_scsi_set_endpoint(struct virtio_dev *device, struct VhostUserMsg *pmsg);\n+\n+#endif\n\\ No newline at end of file\ndiff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c\nindex 90c4b03..320f86b 100644\n--- a/lib/librte_vhost/vhost_user.c\n+++ b/lib/librte_vhost/vhost_user.c\n@@ -50,6 +50,7 @@\n \n #include \"vhost_device.h\"\n #include \"vhost_net.h\"\n+#include \"vhost_scsi.h\"\n #include \"vhost_user.h\"\n \n #define MAX_VHOST_DEVICE        1024\n@@ -76,6 +77,9 @@ static const char *vhost_message_str[VHOST_USER_MAX] = {\n \t[VHOST_USER_GET_QUEUE_NUM]  = \"VHOST_USER_GET_QUEUE_NUM\",\n \t[VHOST_USER_SET_VRING_ENABLE]  = \"VHOST_USER_SET_VRING_ENABLE\",\n \t[VHOST_USER_SEND_RARP]  = \"VHOST_USER_SEND_RARP\",\n+\t[VHOST_USER_SCSI_SET_ENDPOINT] = \"VHOST_USER_SCSI_SET_ENDPOINT\",\n+\t[VHOST_USER_SCSI_CLEAR_ENDPOINT] = \"VHOST_USER_SCSI_CLEAR_ENDPOINT\",\n+\t[VHOST_USER_SCSI_GET_ABI_VERSION] = \"VHOST_USER_SCSI_GET_ABI_VERSION\",\n };\n \n static uint64_t\n@@ -163,6 +167,12 @@ vhost_new_device(int type)\n \t\t\tvhost_net_device_init(dev);\n \t\t\tassert(notify_ops != NULL);\n \t\t\tbreak;\n+\n+\t\tcase VIRTIO_ID_SCSI:\n+\t\t\tdev->notify_ops = scsi_notify_ops;\n+\t\t\tvhost_scsi_device_init(dev);\n+\t\t\tassert(scsi_notify_ops != NULL);\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\treturn -1;\n \t}\n@@ -713,6 +723,11 @@ vhost_user_set_vring_call(struct virtio_dev *dev, struct VhostUserMsg *pmsg)\n \n \tif (dev->fn_table.vhost_dev_set_vring_call)\n \t\tdev->fn_table.vhost_dev_set_vring_call(dev, &file);\n+\n+\tif (virtio_is_ready(dev) && !(dev->flags & VIRTIO_DEV_RUNNING)) {\n+\t\tif (dev->notify_ops->new_device(dev->vid) == 0)\n+\t\t\tdev->flags |= VIRTIO_DEV_RUNNING;\n+\t}\n }\n \n /*\n@@ -740,11 +755,6 @@ vhost_user_set_vring_kick(struct virtio_dev *dev, struct VhostUserMsg *pmsg)\n \t\tclose(vq->kickfd);\n \n \tvq->kickfd = file.fd;\n-\n-\tif (virtio_is_ready(dev) && !(dev->flags & VIRTIO_DEV_RUNNING)) {\n-\t\tif (dev->notify_ops->new_device(dev->vid) == 0)\n-\t\t\tdev->flags |= VIRTIO_DEV_RUNNING;\n-\t}\n }\n \n /*\n@@ -1027,6 +1037,17 @@ vhost_user_msg_handler(int vid, int fd)\n \t\tvhost_user_send_rarp(dev, &msg);\n \t\tbreak;\n \n+\tcase VHOST_USER_SCSI_SET_ENDPOINT:\n+\t\tvhost_user_scsi_set_endpoint(dev, &msg);\n+\t\tbreak;\n+\tcase VHOST_USER_SCSI_CLEAR_ENDPOINT:\n+\t\tbreak;\n+\tcase VHOST_USER_SCSI_GET_ABI_VERSION:\n+\t\tmsg.payload.s32 = VHOST_USER_SCSI_ABI_VERSION;\n+\t\tmsg.size = sizeof(msg.payload.s32);\n+\t\tsend_vhost_message(fd, &msg);\n+\t\tbreak;\n+\n \tdefault:\n \t\tbreak;\n \ndiff --git a/lib/librte_vhost/vhost_user.h b/lib/librte_vhost/vhost_user.h\nindex 59f80f2..dfeb27f 100644\n--- a/lib/librte_vhost/vhost_user.h\n+++ b/lib/librte_vhost/vhost_user.h\n@@ -65,6 +65,9 @@ typedef enum VhostUserRequest {\n \tVHOST_USER_GET_QUEUE_NUM = 17,\n \tVHOST_USER_SET_VRING_ENABLE = 18,\n \tVHOST_USER_SEND_RARP = 19,\n+\tVHOST_USER_SCSI_SET_ENDPOINT = 20,\n+\tVHOST_USER_SCSI_CLEAR_ENDPOINT = 21,\n+\tVHOST_USER_SCSI_GET_ABI_VERSION = 22,\n \tVHOST_USER_MAX\n } VhostUserRequest;\n \n@@ -97,10 +100,12 @@ typedef struct VhostUserMsg {\n #define VHOST_USER_VRING_IDX_MASK   0xff\n #define VHOST_USER_VRING_NOFD_MASK  (0x1<<8)\n \t\tuint64_t u64;\n+\t\tint32_t s32;\n \t\tstruct vhost_vring_state state;\n \t\tstruct vhost_vring_addr addr;\n \t\tVhostUserMemory memory;\n \t\tVhostUserLog    log;\n+\t\tstruct vhost_scsi_target scsi_target;\n \t} payload;\n \tint fds[VHOST_MEMORY_MAX_NREGIONS];\n } __attribute((packed)) VhostUserMsg;\ndiff --git a/lib/librte_vhost/virtio_scsi.c b/lib/librte_vhost/virtio_scsi.c\nnew file mode 100644\nindex 0000000..a49f9ce\n--- /dev/null\n+++ b/lib/librte_vhost/virtio_scsi.c\n@@ -0,0 +1,145 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <stdint.h>\n+#include <stdbool.h>\n+#include <linux/virtio_ring.h>\n+#include <linux/virtio_scsi.h>\n+#include <sys/uio.h>\n+\n+#include <rte_mbuf.h>\n+#include <rte_memcpy.h>\n+#include <rte_virtio_scsi.h>\n+\n+#include \"vhost_scsi.h\"\n+#include \"vhost_device.h\"\n+\n+int\n+rte_vhost_scsi_pop_request(int vid, uint16_t queue_id,\n+\tstruct virtio_scsi_cmd_req **request, struct virtio_scsi_cmd_resp **response, struct iovec *iovs, int *iov_cnt, uint32_t *desc_idx, uint32_t *xfer_direction)\n+{\n+\tstruct virtio_dev *device;\n+\tstruct virtio_scsi *dev;\n+\tstruct vhost_virtqueue *vq;\n+\tstruct vring_desc *desc;\n+\tuint16_t avail_idx;\n+\tuint32_t resp_idx, data_idx;\n+\tuint32_t free_entries;\n+\n+\tdevice = get_device(vid);\n+\tif (!device)\n+\t\treturn 0;\n+\n+\tdev = get_scsi_device(device);\n+\n+\tif (queue_id >= dev->virt_q_nb) {\n+\t\treturn -1;\n+\t}\n+\n+\tvq = dev->virtqueue[queue_id];\n+\tif (unlikely(vq->enabled == 0))\n+\t\treturn 0;\n+\n+\tfree_entries = *((volatile uint16_t *)&vq->avail->idx) -\n+\t\t\tvq->last_avail_idx;\n+\tif (free_entries == 0)\n+\t\treturn 0;\n+\n+\tLOG_DEBUG(VHOST_DATA, \"(%d) %s\\n\", dev->device->vid, __func__);\n+\n+#define FLAGS_NEXT 0x1\n+#define FLAGS_WRITE 0x2\n+\n+\t/* Prefetch available and used ring */\n+\tavail_idx = vq->last_avail_idx & (vq->size - 1);\n+\trte_prefetch0(&vq->avail->ring[avail_idx]);\n+\n+\t*desc_idx = vq->avail->ring[avail_idx];\n+\n+\t/* 1st descriptor */\n+\tdesc = &vq->desc[*desc_idx];\n+\t*request = (void *)gpa_to_vva(device, desc->addr);\n+\t/* 2st descriptor */\n+\tresp_idx = desc->next;\n+\tdesc = &vq->desc[resp_idx];\n+\t*response = (void *)gpa_to_vva(device, desc->addr);\n+\n+\tif (desc->flags & FLAGS_NEXT) {\n+\t\tdata_idx = desc->next;\n+\t\tdesc = &vq->desc[data_idx];\n+\t\tiovs[0].iov_base = (void *)gpa_to_vva(device, desc->addr);\n+\t\tiovs[0].iov_len = desc->len;\n+\t\tif (desc->flags & FLAGS_WRITE)\n+\t\t\t*xfer_direction = DIR_DMA_FROM_DEV;\n+\t\t*iov_cnt = 1;\n+\t}\n+\n+\trte_smp_wmb();\n+\trte_smp_rmb();\n+\tvq->last_avail_idx += 1;\n+\n+\treturn 1;\n+}\n+\n+int\n+rte_vhost_scsi_push_response(int vid, uint16_t queue_id, uint32_t req_idx, uint32_t len)\n+{\n+\tstruct virtio_dev *device;\n+\tstruct virtio_scsi *dev;\n+\tstruct vhost_virtqueue *vq;\n+\n+\tdevice = get_device(vid);\n+\tif (!device)\n+\t\treturn 0;\n+\n+\tdev = get_scsi_device(device);\n+\n+\tif (queue_id >= dev->virt_q_nb) {\n+\t\treturn -1;\n+\t}\n+\n+\tvq = dev->virtqueue[queue_id];\n+\tif (unlikely(vq->enabled == 0))\n+\t\treturn 0;\n+\n+\tvq->used->ring[vq->used->idx & (vq->size - 1)].id = req_idx;\n+\tvq->used->ring[vq->used->idx & (vq->size - 1)].len = len;\n+\n+\trte_smp_wmb();\n+\trte_smp_rmb();\n+\tvq->used->idx++;\n+\n+\teventfd_write(vq->callfd, (eventfd_t)1);\n+\n+\treturn 0;\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "2/2"
    ]
}