get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 85492,
    "url": "https://patches.dpdk.org/api/patches/85492/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20201219062806.56477-5-chenbo.xia@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<20201219062806.56477-5-chenbo.xia@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201219062806.56477-5-chenbo.xia@intel.com",
    "date": "2020-12-19T06:28:02",
    "name": "[v2,4/8] emu/iavf: add vfio-user device register and unregister",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "ba83ed4e2cbef972a9e0e2777f6cb124f3fc6364",
    "submitter": {
        "id": 1276,
        "url": "https://patches.dpdk.org/api/people/1276/?format=api",
        "name": "Chenbo Xia",
        "email": "chenbo.xia@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20201219062806.56477-5-chenbo.xia@intel.com/mbox/",
    "series": [
        {
            "id": 14383,
            "url": "https://patches.dpdk.org/api/series/14383/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14383",
            "date": "2020-12-19T06:27:58",
            "name": "Introduce emudev library and iavf emudev driver",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/14383/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/85492/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/85492/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id D2A37A04B5;\n\tSat, 19 Dec 2020 07:44:39 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 514D2CB69;\n\tSat, 19 Dec 2020 07:43:27 +0100 (CET)",
            "from mga18.intel.com (mga18.intel.com [134.134.136.126])\n by dpdk.org (Postfix) with ESMTP id F0A34CB69\n for <dev@dpdk.org>; Sat, 19 Dec 2020 07:43:24 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 18 Dec 2020 22:43:24 -0800",
            "from npg-dpdk-virtio-xiachenbo-nw.sh.intel.com ([10.67.119.123])\n by fmsmga001.fm.intel.com with ESMTP; 18 Dec 2020 22:43:21 -0800"
        ],
        "IronPort-SDR": [
            "\n VDnEzV2ElxaSjLEBmMgLWgEIek74cZ5PkMD3OLoWVSUD0P0Hb93RkLOkJZkXQ7anh1m0hM4/QG\n rwgvoHu7pBtQ==",
            "\n drW/qdCNskiFGR9DEHnOuzXzkOOR1NaSKGvHqKR1R7Z9tpfBAS0S43+2lDc4FQ1OUnOkTlWV1m\n wuwAz1KDI+Ng=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9839\"; a=\"163285190\"",
            "E=Sophos;i=\"5.78,432,1599548400\"; d=\"scan'208\";a=\"163285190\"",
            "E=Sophos;i=\"5.78,432,1599548400\"; d=\"scan'208\";a=\"454449614\""
        ],
        "X-ExtLoop1": "1",
        "From": "Chenbo Xia <chenbo.xia@intel.com>",
        "To": "dev@dpdk.org,\n\tthomas@monjalon.net,\n\tdavid.marchand@redhat.com",
        "Cc": "stephen@networkplumber.org, cunming.liang@intel.com, xiuchun.lu@intel.com,\n miao.li@intel.com, jingjing.wu@intel.com",
        "Date": "Sat, 19 Dec 2020 14:28:02 +0800",
        "Message-Id": "<20201219062806.56477-5-chenbo.xia@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20201219062806.56477-1-chenbo.xia@intel.com>",
        "References": "<20201218074736.93999-1-chenbo.xia@intel.com>\n <20201219062806.56477-1-chenbo.xia@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2 4/8] emu/iavf: add vfio-user device register\n\tand unregister",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch adds vfio-user APIs call in driver probe and remove.\nrte_vfio_user_register() and rte_vfio_user_unregister() are called\nto create/destroy a vfio-user device. Notify callbacks that\nlibvfio_user defines are also implemented.\n\nSigned-off-by: Chenbo Xia <chenbo.xia@intel.com>\nSigned-off-by: Miao Li <miao.li@intel.com>\n---\n drivers/emu/iavf/iavf_emu.c          |   3 +-\n drivers/emu/iavf/iavf_emu_internal.h |  19 ++\n drivers/emu/iavf/iavf_emudev.c       |  12 +-\n drivers/emu/iavf/iavf_vfio_user.c    | 384 +++++++++++++++++++++++++++\n drivers/emu/iavf/iavf_vfio_user.h    |  16 ++\n drivers/emu/iavf/meson.build         |   5 +-\n drivers/emu/iavf/rte_iavf_emu.h      |  17 ++\n 7 files changed, 452 insertions(+), 4 deletions(-)\n create mode 100644 drivers/emu/iavf/iavf_vfio_user.c\n create mode 100644 drivers/emu/iavf/iavf_vfio_user.h",
    "diff": "diff --git a/drivers/emu/iavf/iavf_emu.c b/drivers/emu/iavf/iavf_emu.c\nindex 68d2c440e3..dfd9796920 100644\n--- a/drivers/emu/iavf/iavf_emu.c\n+++ b/drivers/emu/iavf/iavf_emu.c\n@@ -2,7 +2,7 @@\n  * Copyright(c) 2020 Intel Corporation\n  */\n \n-#include \"iavf_emu_internal.h\"\n+#include \"iavf_vfio_user.h\"\n \n static int iavf_emu_dev_close(struct rte_emudev *dev)\n {\n@@ -18,6 +18,7 @@ static int iavf_emu_dev_close(struct rte_emudev *dev)\n \t}\n \n \tiavf = (struct iavf_emudev *)dev->priv_data;\n+\tiavf_emu_unregister_vfio_user(iavf);\n \tiavf_emu_uninit_device(iavf);\n \tdev->priv_data = NULL;\n \ndiff --git a/drivers/emu/iavf/iavf_emu_internal.h b/drivers/emu/iavf/iavf_emu_internal.h\nindex a726bfe577..10197c00ba 100644\n--- a/drivers/emu/iavf/iavf_emu_internal.h\n+++ b/drivers/emu/iavf/iavf_emu_internal.h\n@@ -17,6 +17,13 @@ extern int emu_iavf_logtype;\n #define EMU_IAVF_LOG(level, ...) \\\n \trte_log(RTE_LOG_ ## level, emu_iavf_logtype, \"EMU_IAVF: \" __VA_ARGS__)\n \n+struct iavf_emu_vfio_user {\n+\tint dev_id;\n+\tstruct vfio_device_info *dev_info;\n+\tstruct rte_vfio_user_regions *reg;\n+\tstruct rte_vfio_user_irq_info *irq;\n+};\n+\n struct iavf_emu_intr_info {\n \tint enable;\n \tint fd;\n@@ -27,6 +34,14 @@ struct iavf_emu_intr {\n \tstruct iavf_emu_intr_info info[RTE_IAVF_EMU_MAX_INTR];\n };\n \n+struct iavf_emu_adminQ {\n+\tuint32_t *ring_addr_lo;\n+\tuint32_t *ring_addr_hi;\n+\tuint32_t *ring_sz;\n+\tuint16_t db_size;\n+\tvoid *doorbell;\n+};\n+\n struct iavf_emu_lanQ {\n \tuint16_t db_size;\n \tvoid *doorbell;\n@@ -34,14 +49,18 @@ struct iavf_emu_lanQ {\n \n struct iavf_emudev {\n \tstruct rte_emudev *edev;\n+\tstruct iavf_emu_vfio_user *vfio;\n \t/* Maximum LANQ queue pair that this emulated iavf has */\n \tuint16_t max_lanqp;\n \t/* Maximum LANQ queue pair number that back-end driver can use */\n \tuint16_t max_be_lanqp;\n \tunsigned int numa_node;\n+\tint ready;\n \tchar *sock_addr;\n+\tstruct rte_iavf_emu_notify_ops *ops;\n \tstruct rte_iavf_emu_mem *mem;\n \tstruct iavf_emu_intr *intr;\n+\tstruct iavf_emu_adminQ adq[RTE_IAVF_EMU_ADMINQ_NUM];\n \tstruct iavf_emu_lanQ *lanq;\n };\n \ndiff --git a/drivers/emu/iavf/iavf_emudev.c b/drivers/emu/iavf/iavf_emudev.c\nindex a4cd2deb06..fbbe3d95a7 100644\n--- a/drivers/emu/iavf/iavf_emudev.c\n+++ b/drivers/emu/iavf/iavf_emudev.c\n@@ -6,7 +6,7 @@\n #include <rte_emudev.h>\n #include <rte_emudev_vdev.h>\n \n-#include \"iavf_emu_internal.h\"\n+#include \"iavf_vfio_user.h\"\n \n #define EMU_IAVF_SOCK_ARG \"sock\"\n #define EMU_IAVF_QUEUES_ARG \"queues\"\n@@ -170,10 +170,20 @@ rte_emu_iavf_probe(struct rte_vdev_device *dev)\n \tiavf->max_lanqp = queues;\n \tedev->priv_data = (void *)iavf;\n \n+\tret = iavf_emu_register_vfio_user(iavf);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR,\n+\t\t\t\"Emulated iavf failed to register vfio user.\\n\");\n+\t\tret = -1;\n+\t\tgoto err_reg;\n+\t}\n+\n \tedev->started = 1;\n \trte_kvargs_free(kvlist);\n \treturn 0;\n \n+err_reg:\n+\tiavf_emu_uninit_device(iavf);\n err_ndev:\n \trte_emudev_release(edev);\n err:\ndiff --git a/drivers/emu/iavf/iavf_vfio_user.c b/drivers/emu/iavf/iavf_vfio_user.c\nnew file mode 100644\nindex 0000000000..aae47de9f3\n--- /dev/null\n+++ b/drivers/emu/iavf/iavf_vfio_user.c\n@@ -0,0 +1,384 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <pthread.h>\n+\n+#include <rte_malloc.h>\n+\n+#include \"iavf_vfio_user.h\"\n+#include <iavf_type.h>\n+\n+struct iavf_emu_sock_list {\n+\tTAILQ_ENTRY(iavf_emu_sock_list) next;\n+\tstruct rte_emudev *emu_dev;\n+};\n+\n+TAILQ_HEAD(iavf_emu_sock_list_head, iavf_emu_sock_list);\n+\n+static struct iavf_emu_sock_list_head sock_list =\n+\tTAILQ_HEAD_INITIALIZER(sock_list);\n+\n+static pthread_mutex_t sock_list_lock = PTHREAD_MUTEX_INITIALIZER;\n+\n+static int iavf_emu_setup_irq(struct iavf_emudev *dev)\n+{\n+\tstruct iavf_emu_intr *intr;\n+\tstruct rte_vfio_user_irq_info *irq;\n+\tint *fds = NULL;\n+\tuint32_t i, count;\n+\n+\tirq = dev->vfio->irq;\n+\tif (!irq)\n+\t\treturn -1;\n+\n+\tcount = irq->irq_info[VFIO_PCI_MSIX_IRQ_INDEX].count;\n+\tif (count) {\n+\t\tfds = rte_zmalloc(\"irq_fds\", sizeof(int) * count, 0);\n+\t\tif (!fds) {\n+\t\t\tEMU_IAVF_LOG(ERR,\n+\t\t\t\t\"Failed to alloc irq fds.\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tif (rte_vfio_user_get_irq(dev->vfio->dev_id,\n+\t\t\tVFIO_PCI_MSIX_IRQ_INDEX, count, fds)) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to get irqfds from vfio-user.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tintr = dev->intr;\n+\tintr->intr_num = irq->irq_info[VFIO_PCI_MSIX_IRQ_INDEX].count;\n+\n+\tfor (i = 0; i < count; i++) {\n+\t\tintr->info[i].fd = fds[i];\n+\t\tintr->info[i].enable = 0;\n+\t}\n+\n+\trte_free(fds);\n+\n+\treturn 0;\n+}\n+\n+static inline void iavf_emu_reset_irq(struct iavf_emudev *dev)\n+{\n+\tstruct iavf_emu_intr *intr = dev->intr;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < intr->intr_num; i++) {\n+\t\tintr->info[i].enable = 0;\n+\t\tintr->info[i].fd = -1;\n+\t}\n+}\n+\n+static inline void iavf_emu_reset_regions(struct iavf_emudev *dev)\n+{\n+\tstruct rte_vfio_user_regions *reg = dev->vfio->reg;\n+\tstruct rte_vfio_user_reg_info *vinfo;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < reg->reg_num; i++) {\n+\t\tvinfo = &reg->reg_info[i];\n+\t\tif (vinfo->info->size && vinfo->base)\n+\t\t\tmemset(vinfo->base, 0, vinfo->info->size);\n+\t}\n+}\n+\n+static int iavf_emu_setup_mem_table(struct iavf_emudev *dev)\n+{\n+\tconst struct rte_vfio_user_mem *vfio_mem;\n+\tconst struct rte_vfio_user_mtb_entry *entry;\n+\tstruct rte_iavf_emu_mem *mem;\n+\tuint32_t i;\n+\n+\tvfio_mem = rte_vfio_user_get_mem_table(dev->vfio->dev_id);\n+\tif (!vfio_mem) {\n+\t\tEMU_IAVF_LOG(ERR, \"Unable to get vfio mem table.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tmem = dev->mem;\n+\n+\tmem->region_num = vfio_mem->entry_num;\n+\tif (mem->region_num > RTE_IAVF_EMU_MAX_MEM_REGIONS) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set up mem table,\"\n+\t\t\t\"exceed max region num.\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tfor (i = 0; i < vfio_mem->entry_num; i++) {\n+\t\tentry = &vfio_mem->entry[i];\n+\n+\t\tmem->regions[i].guest_phys_addr = entry->gpa;\n+\t\tmem->regions[i].host_user_addr = entry->host_user_addr;\n+\t\tmem->regions[i].mmap_addr = entry->mmap_addr;\n+\t\tmem->regions[i].mmap_size = entry->mmap_size;\n+\t\tmem->regions[i].size = entry->size;\n+\t\tmem->regions[i].fd = entry->fd;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static inline void iavf_emu_reset_mem_table(struct iavf_emudev *dev)\n+{\n+\tstruct rte_iavf_emu_mem *mem = dev->mem;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < mem->region_num; i++) {\n+\t\tmem->regions[i].guest_phys_addr = 0;\n+\t\tmem->regions[i].host_user_addr = 0;\n+\t\tmem->regions[i].mmap_addr = 0;\n+\t\tmem->regions[i].mmap_size = 0;\n+\t\tmem->regions[i].size = 0;\n+\t\tmem->regions[i].fd = -1;\n+\t}\n+}\n+\n+static int iavf_emu_setup_queues(struct iavf_emudev *dev)\n+{\n+\tstruct iavf_emu_adminQ *asq, *arq;\n+\tstruct rte_vfio_user_reg_info *info;\n+\tuint16_t i;\n+\n+\tinfo = &dev->vfio->reg->reg_info[0];\n+\tasq = &dev->adq[RTE_IAVF_EMU_ADMINQ_TXQ];\n+\tarq = &dev->adq[RTE_IAVF_EMU_ADMINQ_RXQ];\n+\n+\tasq->doorbell = (uint8_t *)info->base + IAVF_VF_ATQT1;\n+\tasq->db_size = 4;\n+\tasq->ring_addr_lo = (uint32_t *)((uint8_t *)info->base +\n+\t\t\t\tIAVF_VF_ATQBAL1);\n+\tasq->ring_addr_hi = (uint32_t *)((uint8_t *)info->base +\n+\t\t\t\tIAVF_VF_ATQBAH1);\n+\tasq->ring_sz = (uint32_t *)((uint8_t *)info->base + IAVF_VF_ATQLEN1);\n+\n+\tarq->doorbell = (uint8_t *)info->base + IAVF_VF_ARQT1;\n+\tarq->db_size = 4;\n+\tarq->ring_addr_lo = (uint32_t *)((uint8_t *)info->base +\n+\t\t\t\tIAVF_VF_ARQBAL1);\n+\tarq->ring_addr_hi = (uint32_t *)((uint8_t *)info->base +\n+\t\t\t\tIAVF_VF_ARQBAH1);\n+\tarq->ring_sz = (uint32_t *)((uint8_t *)info->base + IAVF_VF_ARQLEN1);\n+\n+\tfor (i = 0; i < dev->max_lanqp; i++) {\n+\t\tdev->lanq[i * 2].doorbell = (uint8_t *)info->base +\n+\t\t\t\tIAVF_QTX_TAIL1(i);\n+\t\tdev->lanq[i * 2].db_size = 4;\n+\t\tdev->lanq[i * 2 + 1].doorbell = (uint8_t *)info->base +\n+\t\t\t\tIAVF_QRX_TAIL1(i);\n+\t\tdev->lanq[i * 2 + 1].db_size = 4;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static inline void iavf_emu_reset_queues(struct iavf_emudev *dev)\n+{\n+\tmemset(&dev->adq, 0, RTE_IAVF_EMU_ADMINQ_NUM *\n+\t\tsizeof(struct iavf_emu_adminQ));\n+\n+\tmemset(dev->lanq, 0, dev->max_lanqp * 2 *\n+\t\tsizeof(struct iavf_emu_lanQ));\n+}\n+\n+static void iavf_emu_reset_all_resources(struct iavf_emudev *dev)\n+{\n+\tiavf_emu_reset_mem_table(dev);\n+\tiavf_emu_reset_irq(dev);\n+\tiavf_emu_reset_queues(dev);\n+\tiavf_emu_reset_regions(dev);\n+}\n+\n+static inline struct iavf_emu_sock_list *\n+iavf_emu_find_sock_list(char *sock_addr)\n+{\n+\tstruct iavf_emu_sock_list *list;\n+\tstruct iavf_emudev *dev;\n+\tint list_exist;\n+\n+\tif (!sock_addr)\n+\t\treturn NULL;\n+\n+\tpthread_mutex_lock(&sock_list_lock);\n+\n+\tTAILQ_FOREACH(list, &sock_list, next) {\n+\t\tdev = (struct iavf_emudev *)list->emu_dev->priv_data;\n+\n+\t\tif (!strcmp(dev->sock_addr, sock_addr)) {\n+\t\t\tlist_exist = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\n+\tpthread_mutex_unlock(&sock_list_lock);\n+\n+\tif (!list_exist)\n+\t\treturn NULL;\n+\n+\treturn list;\n+}\n+\n+static struct iavf_emudev *find_iavf_with_dev_id(int vfio_dev_id)\n+{\n+\tstruct iavf_emu_sock_list *list;\n+\tchar sock_addr[PATH_MAX];\n+\tint ret;\n+\n+\tret = rte_vfio_get_sock_addr(vfio_dev_id, sock_addr,\n+\t\tsizeof(sock_addr));\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Can not find vfio device %d \"\n+\t\t\t\"sock_addr.\\n\", vfio_dev_id);\n+\t\treturn NULL;\n+\t}\n+\n+\tlist = iavf_emu_find_sock_list(sock_addr);\n+\tif (!list) {\n+\t\tEMU_IAVF_LOG(ERR, \"Can not find sock list.\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\treturn (struct iavf_emudev *)list->emu_dev->priv_data;\n+}\n+\n+static int iavf_emu_new_device(int vfio_dev_id)\n+{\n+\tstruct iavf_emudev *dev;\n+\tint ret;\n+\n+\tdev = find_iavf_with_dev_id(vfio_dev_id);\n+\tif (!dev)\n+\t\treturn -1;\n+\n+\tdev->vfio->dev_id = vfio_dev_id;\n+\n+\tret = iavf_emu_setup_mem_table(dev);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set up memtable for \"\n+\t\t\t\"device %d\", dev->vfio->dev_id);\n+\t\treturn ret;\n+\t}\n+\n+\tret = iavf_emu_setup_irq(dev);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set up irq for \"\n+\t\t\t\"device %d\", dev->vfio->dev_id);\n+\t\treturn ret;\n+\t}\n+\n+\tret = iavf_emu_setup_queues(dev);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set up queues for \"\n+\t\t\t\"device %d\", dev->vfio->dev_id);\n+\t\treturn ret;\n+\t}\n+\n+\tret = dev->ops->device_ready(dev->edev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev->ready = 1;\n+\treturn 0;\n+}\n+\n+static void iavf_emu_destroy_device(int vfio_dev_id)\n+{\n+\tstruct iavf_emudev *dev;\n+\n+\tdev = find_iavf_with_dev_id(vfio_dev_id);\n+\tif (!dev)\n+\t\treturn;\n+\n+\tiavf_emu_reset_all_resources(dev);\n+\n+\tdev->ops->device_destroy(dev->edev);\n+}\n+\n+static int iavf_emu_update_status(int vfio_dev_id)\n+{\n+\tstruct iavf_emudev *dev;\n+\tint ret;\n+\n+\tdev = find_iavf_with_dev_id(vfio_dev_id);\n+\tif (!dev)\n+\t\treturn -1;\n+\n+\tret = iavf_emu_setup_mem_table(dev);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set up memtable for \"\n+\t\t\t\"device %d\", dev->vfio->dev_id);\n+\t\treturn ret;\n+\t}\n+\n+\tret = iavf_emu_setup_irq(dev);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set up irq for \"\n+\t\t\t\"device %d\", dev->vfio->dev_id);\n+\t\treturn ret;\n+\t}\n+\n+\tdev->ops->update_status(dev->edev);\n+\n+\treturn 0;\n+}\n+\n+static int iavf_emu_lock_datapath(int vfio_dev_id, int lock)\n+{\n+\tstruct iavf_emudev *dev;\n+\n+\tdev = find_iavf_with_dev_id(vfio_dev_id);\n+\tif (!dev)\n+\t\treturn -1;\n+\n+\treturn dev->ops->lock_dp(dev->edev, lock);\n+}\n+\n+static int iavf_emu_reset_device(int vfio_dev_id)\n+{\n+\tstruct iavf_emudev *dev;\n+\n+\tdev = find_iavf_with_dev_id(vfio_dev_id);\n+\tif (!dev)\n+\t\treturn -1;\n+\n+\tiavf_emu_reset_all_resources(dev);\n+\n+\treturn dev->ops->reset_device(dev->edev);\n+}\n+\n+struct rte_vfio_user_notify_ops vfio_ops = {\n+\t.new_device = iavf_emu_new_device,\n+\t.destroy_device = iavf_emu_destroy_device,\n+\t.update_status = iavf_emu_update_status,\n+\t.lock_dp = iavf_emu_lock_datapath,\n+\t.reset_device = iavf_emu_reset_device,\n+};\n+\n+int iavf_emu_register_vfio_user(struct iavf_emudev *dev)\n+{\n+\tint ret;\n+\n+\tret = rte_vfio_user_register(dev->sock_addr, &vfio_ops);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Register vfio_user failed\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int iavf_emu_unregister_vfio_user(struct iavf_emudev *dev)\n+{\n+\tint ret;\n+\n+\tret = rte_vfio_user_unregister(dev->sock_addr);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Unregister vfio_user failed\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/emu/iavf/iavf_vfio_user.h b/drivers/emu/iavf/iavf_vfio_user.h\nnew file mode 100644\nindex 0000000000..aa2f3edc87\n--- /dev/null\n+++ b/drivers/emu/iavf/iavf_vfio_user.h\n@@ -0,0 +1,16 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _IAVF_VFIO_USER_H\n+#define _IAVF_VFIO_USER_H\n+\n+#include <rte_vfio_user.h>\n+\n+#include \"iavf_emu_internal.h\"\n+\n+int iavf_emu_register_vfio_user(struct iavf_emudev *dev);\n+\n+int iavf_emu_unregister_vfio_user(struct iavf_emudev *dev);\n+\n+#endif\ndiff --git a/drivers/emu/iavf/meson.build b/drivers/emu/iavf/meson.build\nindex 58c2a90383..4f651258c2 100644\n--- a/drivers/emu/iavf/meson.build\n+++ b/drivers/emu/iavf/meson.build\n@@ -1,8 +1,9 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright(c) 2020 Intel Corporation\n \n-sources = files('iavf_emu.c', 'iavf_emudev.c')\n+sources = files('iavf_emu.c', 'iavf_vfio_user.c',\n+\t'iavf_emudev.c')\n \n-deps += ['bus_vdev', 'emudev']\n+deps += ['bus_vdev', 'emudev', 'vfio_user', 'common_iavf']\n \n headers = files('rte_iavf_emu.h')\ndiff --git a/drivers/emu/iavf/rte_iavf_emu.h b/drivers/emu/iavf/rte_iavf_emu.h\nindex 623c3c5d99..6de0989f0b 100644\n--- a/drivers/emu/iavf/rte_iavf_emu.h\n+++ b/drivers/emu/iavf/rte_iavf_emu.h\n@@ -40,4 +40,21 @@ struct rte_iavf_emu_mem {\n \tstruct rte_iavf_emu_mem_reg regions[RTE_IAVF_EMU_MAX_MEM_REGIONS];\n };\n \n+struct rte_iavf_emu_notify_ops {\n+\t/* Device is ready */\n+\tint (*device_ready)(struct rte_emudev *dev);\n+\t/* Device is destroyed */\n+\tvoid (*device_destroy)(struct rte_emudev *dev);\n+\t/* Update device status */\n+\tint (*update_status)(struct rte_emudev *dev);\n+\t/* Start device */\n+\tint (*device_start)(struct rte_emudev *dev);\n+\t/* Stop device */\n+\tint (*device_stop)(struct rte_emudev *dev);\n+\t/* Lock or unlock data path */\n+\tint (*lock_dp)(struct rte_emudev *dev, int lock);\n+\t/* Reset device */\n+\tint (*reset_device)(struct rte_emudev *dev);\n+};\n+\n #endif\n",
    "prefixes": [
        "v2",
        "4/8"
    ]
}