get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 86513,
    "url": "https://patches.dpdk.org/api/patches/86513/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210114062512.45462-6-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": "<20210114062512.45462-6-chenbo.xia@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210114062512.45462-6-chenbo.xia@intel.com",
    "date": "2021-01-14T06:25:09",
    "name": "[v3,5/8] emu/iavf: add resource management and internal logic of iavf",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "8db8ca3a0965837c8841b76cf183e4b88b473bdc",
    "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/20210114062512.45462-6-chenbo.xia@intel.com/mbox/",
    "series": [
        {
            "id": 14712,
            "url": "https://patches.dpdk.org/api/series/14712/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14712",
            "date": "2021-01-14T06:25:04",
            "name": "Introduce emudev library and iavf emudev driver",
            "version": 3,
            "mbox": "https://patches.dpdk.org/series/14712/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/86513/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/86513/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 0A626A0A02;\n\tThu, 14 Jan 2021 07:30:57 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id A7223140E45;\n\tThu, 14 Jan 2021 07:30:24 +0100 (CET)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n by mails.dpdk.org (Postfix) with ESMTP id 6C464140E42\n for <dev@dpdk.org>; Thu, 14 Jan 2021 07:30:22 +0100 (CET)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 13 Jan 2021 22:30:22 -0800",
            "from npg-dpdk-virtio-xiachenbo-nw.sh.intel.com ([10.67.119.123])\n by fmsmga002.fm.intel.com with ESMTP; 13 Jan 2021 22:30:19 -0800"
        ],
        "IronPort-SDR": [
            "\n rSfMlH/TLB146nitaXgDFgPbvvv4JH4hDT5gUEsnTpCnlA/vipJ9nFNFupoWAk2evxhVauoKNd\n 5V+RyBrHak7g==",
            "\n jH8m569lhUulQyoytHw7eEikjjkLQ/8EvBZgMnk4a3t8NnbZ+FOHDyL5LrWI0MpgKOPlE/sT8U\n wh1JBn4FVkiw=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9863\"; a=\"178407168\"",
            "E=Sophos;i=\"5.79,346,1602572400\"; d=\"scan'208\";a=\"178407168\"",
            "E=Sophos;i=\"5.79,346,1602572400\"; d=\"scan'208\";a=\"400799452\""
        ],
        "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, beilei.xing@intel.com",
        "Date": "Thu, 14 Jan 2021 14:25:09 +0800",
        "Message-Id": "<20210114062512.45462-6-chenbo.xia@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20210114062512.45462-1-chenbo.xia@intel.com>",
        "References": "<20201219062806.56477-1-chenbo.xia@intel.com>\n <20210114062512.45462-1-chenbo.xia@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 5/8] emu/iavf: add resource management and\n internal logic of iavf",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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 the allocation and release of device resources.\nDevice resources include PCI BARs' memory and interrupt related\nresources. Device internal logic is also added.\n\nSigned-off-by: Chenbo Xia <chenbo.xia@intel.com>\nSigned-off-by: Xiuchun Lu <xiuchun.lu@intel.com>\n---\n drivers/emu/iavf/iavf_emu.c       |   1 +\n drivers/emu/iavf/iavf_emudev.c    |  20 +\n drivers/emu/iavf/iavf_vfio_user.c | 683 +++++++++++++++++++++++++++++-\n drivers/emu/iavf/iavf_vfio_user.h |  41 ++\n drivers/emu/iavf/meson.build      |   8 +\n 5 files changed, 750 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/drivers/emu/iavf/iavf_emu.c b/drivers/emu/iavf/iavf_emu.c\nindex 2f1513137c..7506849e42 100644\n--- a/drivers/emu/iavf/iavf_emu.c\n+++ b/drivers/emu/iavf/iavf_emu.c\n@@ -19,6 +19,7 @@ iavf_emu_dev_close(struct rte_emudev *dev)\n \t}\n \n \tiavf = (struct iavf_emudev *)dev->priv_data;\n+\tiavf_emu_uninit_vfio_user(iavf);\n \tiavf_emu_unregister_vfio_user(iavf);\n \tiavf_emu_uninit_device(iavf);\n \tdev->priv_data = NULL;\ndiff --git a/drivers/emu/iavf/iavf_emudev.c b/drivers/emu/iavf/iavf_emudev.c\nindex 6ba1cc2a89..74f4829e7f 100644\n--- a/drivers/emu/iavf/iavf_emudev.c\n+++ b/drivers/emu/iavf/iavf_emudev.c\n@@ -180,10 +180,30 @@ rte_emu_iavf_probe(struct rte_vdev_device *dev)\n \t\tgoto err_reg;\n \t}\n \n+\tret = iavf_emu_init_vfio_user(iavf);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR,\n+\t\t\t\"Emulated iavf failed to init vfio user.\\n\");\n+\t\tret = -1;\n+\t\tgoto err_init;\n+\t}\n+\n+\tret = iavf_emu_start_vfio_user(iavf);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR,\n+\t\t\t\"Emulated iavf failed to start vfio user.\\n\");\n+\t\tret = -1;\n+\t\tgoto err_start;\n+\t}\n+\n \tedev->started = 1;\n \trte_kvargs_free(kvlist);\n \treturn 0;\n \n+err_start:\n+\tiavf_emu_uninit_vfio_user(iavf);\n+err_init:\n+\tiavf_emu_unregister_vfio_user(iavf);\n err_reg:\n \tiavf_emu_uninit_device(iavf);\n err_ndev:\ndiff --git a/drivers/emu/iavf/iavf_vfio_user.c b/drivers/emu/iavf/iavf_vfio_user.c\nindex 0cc4c433c2..5c690978bd 100644\n--- a/drivers/emu/iavf/iavf_vfio_user.c\n+++ b/drivers/emu/iavf/iavf_vfio_user.c\n@@ -2,13 +2,36 @@\n  * Copyright(c) 2020 Intel Corporation\n  */\n \n+#include <linux/pci.h>\n+#include <string.h>\n+#include <stdint.h>\n+#include <sys/mman.h>\n+#include <sys/stat.h>\n+#include <fcntl.h>\n+#include <unistd.h>\n #include <pthread.h>\n+#include <sys/types.h>\n \n #include <rte_malloc.h>\n+#include <rte_emudev.h>\n+#include <rte_memcpy.h>\n \n #include \"iavf_vfio_user.h\"\n #include <iavf_type.h>\n \n+#define STORE_LE16(addr, val)   (*(__u16 *)addr = val)\n+#define STORE_LE32(addr, val)   (*(__u32 *)addr = val)\n+\n+#define IAVF_EMU_BAR0_SIZE 0x10000\n+#define IAVF_EMU_BAR3_SIZE 0x1000\n+#define IAVF_EMU_BAR_SIZE_MASK 0xffffffff\n+#define IAVF_EMU_BAR_MASK(sz) (~(sz) + 1)\n+#define IAVF_EMU_MSIX_TABLE_SIZE 0x20\n+\n+#define PCI_VENDOR_ID_INTEL 0x8086\n+#define PCI_SUBDEVICE_ID 0x1100\n+#define PCI_CLASS_ETHERNET 0x0200\n+\n struct iavf_emu_sock_list {\n \tTAILQ_ENTRY(iavf_emu_sock_list) next;\n \tstruct rte_emudev *emu_dev;\n@@ -52,10 +75,8 @@ iavf_emu_setup_irq(struct iavf_emudev *dev)\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+\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@@ -199,6 +220,591 @@ iavf_emu_reset_all_resources(struct iavf_emudev *dev)\n \tiavf_emu_reset_regions(dev);\n }\n \n+static int\n+iavf_emu_init_dev(struct iavf_emudev *dev)\n+{\n+\tstruct iavf_emu_vfio_user *vfio;\n+\tstruct vfio_device_info *dev_info;\n+\tstruct rte_vfio_user_regions *reg;\n+\tstruct rte_vfio_user_irq_info *irq;\n+\tstruct vfio_region_info_cap_sparse_mmap *sparse;\n+\tint ret;\n+\tuint32_t i, j;\n+\n+\tvfio = rte_zmalloc_socket(\"vfio\", sizeof(*vfio), 0, dev->numa_node);\n+\tif (!vfio) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to alloc iavf_emu_vfio_user\\n\");\n+\t\tret = -1;\n+\t\tgoto exit;\n+\t}\n+\n+\tdev_info = rte_zmalloc_socket(\"vfio_dev_info\",\n+\t\tsizeof(*dev_info), 0, dev->numa_node);\n+\tif (!dev_info) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to alloc vfio dev_info\\n\");\n+\t\tret = -1;\n+\t\tgoto err_info;\n+\t}\n+\tdev_info->argsz = sizeof(*dev_info);\n+\tdev_info->flags = VFIO_DEVICE_FLAGS_PCI | VFIO_DEVICE_FLAGS_RESET;\n+\tdev_info->num_regions = VFIO_PCI_NUM_REGIONS;\n+\tdev_info->num_irqs = VFIO_PCI_NUM_IRQS;\n+\n+\treg = rte_zmalloc_socket(\"vfio_user_regions\",\n+\t\tsizeof(*reg) + dev_info->num_regions *\n+\t\tsizeof(struct rte_vfio_user_reg_info), 0, dev->numa_node);\n+\tif (!reg) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to alloc vfio_user_regions\\n\");\n+\t\tret = -1;\n+\t\tgoto err_reg;\n+\t}\n+\treg->reg_num = dev_info->num_regions;\n+\n+\tfor (i = 0; i < reg->reg_num; i++) {\n+\t\tstruct rte_vfio_user_reg_info *vinfo = &reg->reg_info[i];\n+\t\tsize_t sz = sizeof(struct vfio_region_info);\n+\n+\t\t/* BAR0 has two sparse mmap area */\n+\t\tif (i == VFIO_PCI_BAR0_REGION_INDEX)\n+\t\t\tsz += sizeof(*sparse) + 2 * sizeof(*sparse->areas);\n+\n+\t\tvinfo->info = rte_zmalloc_socket(\"vfio_region_info\",\n+\t\t\tsz, 0, dev->numa_node);\n+\t\tif (!vinfo->info) {\n+\t\t\tEMU_IAVF_LOG(ERR, \"Failed to alloc region info \"\n+\t\t\t\t\"for region %d\\n\", i);\n+\t\t\tret = -1;\n+\t\t\tgoto err_reg_alloc;\n+\t\t}\n+\n+\t\tvinfo->info->index = i;\n+\n+\t\tswitch (i) {\n+\t\tcase VFIO_PCI_CONFIG_REGION_INDEX:\n+\t\t\tvinfo->info->argsz = sz;\n+\t\t\tvinfo->info->offset = 0;\n+\t\t\tvinfo->info->size = IAVF_EMU_CFG_SPACE_SIZE;\n+\t\t\tvinfo->info->flags = VFIO_REGION_INFO_FLAG_READ |\n+\t\t\t\t       VFIO_REGION_INFO_FLAG_WRITE;\n+\t\t\tbreak;\n+\t\tcase VFIO_PCI_BAR0_REGION_INDEX:\n+\t\t\tvinfo->info->argsz = sz;\n+\t\t\tvinfo->info->offset = 0;\n+\t\t\tvinfo->info->size = IAVF_EMU_BAR0_SIZE;\n+\t\t\tvinfo->info->flags  = VFIO_REGION_INFO_FLAG_READ |\n+\t\t\t\t       VFIO_REGION_INFO_FLAG_WRITE |\n+\t\t\t\t       VFIO_REGION_INFO_FLAG_MMAP |\n+\t\t\t\t       VFIO_REGION_INFO_FLAG_CAPS;\n+\t\t\tvinfo->info->cap_offset =\n+\t\t\t\t\t\tsizeof(struct vfio_region_info);\n+\n+\t\t\tsparse = (struct vfio_region_info_cap_sparse_mmap *)\n+\t\t\t\t\t\t((uint8_t *)vinfo->info +\n+\t\t\t\t\t\tvinfo->info->cap_offset);\n+\t\t\tsparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;\n+\t\t\tsparse->header.version = 1;\n+\t\t\tsparse->nr_areas = 2;\n+\t\t\tsparse->areas[0].offset = 0;\n+\t\t\tsparse->areas[0].size = 0x3000;\n+\t\t\tsparse->areas[1].offset = 0x6000;\n+\t\t\tsparse->areas[1].size = IAVF_EMU_BAR0_SIZE - 0x6000;\n+\n+\t\t\tbreak;\n+\t\tcase VFIO_PCI_BAR3_REGION_INDEX:\n+\t\t\tvinfo->info->argsz = sz;\n+\t\t\tvinfo->info->offset = 0;\n+\t\t\tvinfo->info->size = IAVF_EMU_BAR3_SIZE;\n+\t\t\tvinfo->info->flags  = VFIO_REGION_INFO_FLAG_READ |\n+\t\t\t\t       VFIO_REGION_INFO_FLAG_WRITE |\n+\t\t\t\t       VFIO_REGION_INFO_FLAG_MMAP;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tvinfo->info->argsz = sz;\n+\t\t\tvinfo->info->offset = 0;\n+\t\t\tvinfo->info->size = 0;\n+\t\t\tvinfo->info->flags = 0;\n+\t\t}\n+\t}\n+\n+\tirq = rte_zmalloc_socket(\"vfio_user_irq_info\", sizeof(*irq) +\n+\t\tVFIO_PCI_NUM_IRQS * sizeof(struct vfio_irq_info),\n+\t\t0, dev->numa_node);\n+\tif (!irq) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to alloc vfio_user_irqs\\n\");\n+\t\tret = -1;\n+\t\tgoto err_irq;\n+\t}\n+\tirq->irq_num = VFIO_PCI_NUM_IRQS;\n+\n+\tfor (i = 0; i < VFIO_PCI_NUM_IRQS; i++) {\n+\t\tirq->irq_info[i].index = i;\n+\t\tirq->irq_info[i].flags =\n+\t\t\tVFIO_IRQ_INFO_EVENTFD | VFIO_IRQ_INFO_NORESIZE;\n+\t\tif (i == VFIO_PCI_MSIX_IRQ_INDEX)\n+\t\t\tirq->irq_info[i].count =\n+\t\t\t\tIAVF_EMU_MSIX_TABLE_SIZE + 1;\n+\t\telse if (i == VFIO_PCI_ERR_IRQ_INDEX)\n+\t\t\tirq->irq_info[i].count = 1;\n+\t\telse\n+\t\t\tirq->irq_info[i].count = 0;\n+\t}\n+\n+\tvfio->dev_info = dev_info;\n+\tvfio->reg = reg;\n+\tvfio->irq = irq;\n+\tdev->vfio = vfio;\n+\n+\treturn 0;\n+\n+err_irq:\n+err_reg_alloc:\n+\tfor (j = 0; j < i; j++)\n+\t\trte_free(reg->reg_info[j].info);\n+\trte_free(reg);\n+err_reg:\n+\trte_free(dev_info);\n+err_info:\n+\trte_free(vfio);\n+exit:\n+\treturn ret;\n+}\n+\n+static int\n+iavf_emu_uninit_dev(struct iavf_emudev *dev)\n+{\n+\tstruct iavf_emu_vfio_user *vfio;\n+\tstruct rte_vfio_user_regions *reg;\n+\tuint32_t i;\n+\n+\tif (!dev->vfio)\n+\t\treturn -1;\n+\n+\tvfio = dev->vfio;\n+\trte_free(vfio->dev_info);\n+\n+\treg = vfio->reg;\n+\tfor (i = 0; i < reg->reg_num; i++)\n+\t\trte_free(reg->reg_info[i].info);\n+\trte_free(reg);\n+\n+\trte_free(vfio->irq);\n+\trte_free(vfio);\n+\n+\treturn 0;\n+}\n+\n+static int\n+handle_pci_cmd_write(struct iavf_emu_pci_hdr *hdr,\n+\tchar *buf, size_t count)\n+{\n+\t/* Below are all R/W bits in command register */\n+\tuint16_t rw_bitmask = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |\n+\t\tPCI_COMMAND_MASTER | PCI_COMMAND_PARITY |\n+\t\tPCI_COMMAND_SERR | PCI_COMMAND_INTX_DISABLE;\n+\tuint16_t val;\n+\n+\tif (count != 2) {\n+\t\tEMU_IAVF_LOG(ERR, \"Wrong write count (%lu) for PCI_COMMAND\\n\",\n+\t\t\tcount);\n+\t\treturn -1;\n+\t}\n+\n+\tval = *(uint16_t *)buf;\n+\t/* Only write the R/W bits */\n+\thdr->cmd = (rw_bitmask & val) | (~rw_bitmask & hdr->cmd);\n+\n+\treturn 2;\n+}\n+\n+static int\n+handle_pci_status_write(struct iavf_emu_pci_hdr *hdr,\n+\tchar *buf, size_t count)\n+{\n+\t/* Below are all write-1-to-clear bits in status register */\n+\tuint16_t rw1c_bitmask = PCI_STATUS_PARITY |\n+\t\tPCI_STATUS_SIG_TARGET_ABORT |\n+\t\tPCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT |\n+\t\tPCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY;\n+\tuint16_t val;\n+\n+\tif (count != 2) {\n+\t\tEMU_IAVF_LOG(ERR, \"Wrong write count (%lu) for PCI_STATUS\\n\",\n+\t\t\tcount);\n+\t\treturn -1;\n+\t}\n+\n+\tval = *(uint16_t *)buf;\n+\t/* Clear the write-1-to-clear bits*/\n+\thdr->status = ~(rw1c_bitmask & val) & hdr->status;\n+\n+\treturn 2;\n+}\n+\n+static int\n+handle_pci_bar_write(struct iavf_emu_pci_hdr *hdr,\n+\tchar *buf, size_t count, loff_t pos)\n+{\n+\tuint32_t val, size;\n+\tuint8_t idx;\n+\n+\tif (count != 4) {\n+\t\tEMU_IAVF_LOG(ERR, \"Wrong write count (%lu) for \"\n+\t\t\t\"Base Address Register\\n\",\n+\t\t\tcount);\n+\t\treturn -1;\n+\t}\n+\n+\tval = *(uint32_t *)buf;\n+\n+\tif (pos == PCI_BASE_ADDRESS_0)\n+\t\tsize = IAVF_EMU_BAR0_SIZE;\n+\telse if (pos == PCI_BASE_ADDRESS_3)\n+\t\tsize = IAVF_EMU_BAR3_SIZE;\n+\telse\n+\t\tsize = 0;\n+\n+\tif (val == IAVF_EMU_BAR_SIZE_MASK)\n+\t\tval &= IAVF_EMU_BAR_MASK(size);\n+\n+\tidx = (pos - PCI_BASE_ADDRESS_0) / 0x4;\n+\thdr->bar[idx] |= val & ~PCI_BASE_ADDRESS_MEM_MASK;\n+\n+\treturn 4;\n+}\n+\n+static int\n+handle_cfg_write(struct iavf_emu_pci_hdr *hdr,\n+\tchar *buf, size_t count, loff_t pos)\n+{\n+\tint ret = count;\n+\n+\tswitch (pos) {\n+\tcase PCI_COMMAND:\n+\t\tret = handle_pci_cmd_write(hdr, buf, count);\n+\t\tbreak;\n+\tcase PCI_STATUS:\n+\t\tret = handle_pci_status_write(hdr, buf, count);\n+\t\tbreak;\n+\tcase PCI_INTERRUPT_LINE:\n+\t\tif (count != 1) {\n+\t\t\tEMU_IAVF_LOG(ERR, \"Wrong write count (%lu)\"\n+\t\t\t\t\"for PCI_INTERRUPT_LINE\\n\",\n+\t\t\t\tcount);\n+\t\t\treturn -1;\n+\t\t}\n+\t\thdr->intrl = *(uint8_t *)buf;\n+\t\tret = 1;\n+\t\tbreak;\n+\tcase PCI_BASE_ADDRESS_0:\n+\t\t/* FALLTHROUGH */\n+\tcase PCI_BASE_ADDRESS_1:\n+\t\t/* FALLTHROUGH */\n+\tcase PCI_BASE_ADDRESS_2:\n+\t\t/* FALLTHROUGH */\n+\tcase PCI_BASE_ADDRESS_3:\n+\t\t/* FALLTHROUGH */\n+\tcase PCI_BASE_ADDRESS_4:\n+\t\t/* FALLTHROUGH */\n+\tcase PCI_BASE_ADDRESS_5:\n+\t\tret = handle_pci_bar_write(hdr, buf, count, pos);\n+\t\tbreak;\n+\tdefault:\n+\t\tEMU_IAVF_LOG(INFO, \"Write request for cfg (pos: %ld) ignored\\n\",\n+\t\t\tpos);\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static ssize_t\n+iavf_emu_cfg_rw(struct rte_vfio_user_reg_info *reg, char *buf,\n+\tsize_t count, loff_t pos, bool iswrite)\n+{\n+\tstruct iavf_emu_cfg_space *cfg;\n+\tchar *reg_pos;\n+\tint ret = 0;\n+\n+\tif (!reg->base) {\n+\t\tEMU_IAVF_LOG(ERR, \"Config space not exist\\n\");\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tif (pos + count > reg->info->size) {\n+\t\tEMU_IAVF_LOG(ERR, \"Access exceeds config space size\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tcfg = (struct iavf_emu_cfg_space *)reg->base;\n+\treg_pos = (char *)reg->base + pos;\n+\n+\tif (!iswrite) {\n+\t\trte_memcpy(buf, reg_pos, count);\n+\t\tret = count;\n+\t} else {\n+\t\tret = handle_cfg_write(&cfg->hdr, buf, count, pos);\n+\t\tif (ret < 0) {\n+\t\t\tEMU_IAVF_LOG(ERR, \"Failed to write cfg space\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n+iavf_emu_init_cfg_space(struct rte_vfio_user_reg_info *vinfo,\n+\tunsigned int numa_node)\n+{\n+\tchar *v_cfg;\n+\n+\tvinfo->base = rte_zmalloc_socket(\"cfg space\",\n+\t\tIAVF_EMU_CFG_SPACE_SIZE,\n+\t\t0, numa_node);\n+\tif (!vinfo->base) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to alloc cfg space\\n\");\n+\t\treturn -1;\n+\t}\n+\tvinfo->rw = iavf_emu_cfg_rw;\n+\tvinfo->fd = -1;\n+\tvinfo->priv = NULL;\n+\n+\tv_cfg = (char *)vinfo->base;\n+\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_VENDOR_ID],\n+\t\tPCI_VENDOR_ID_INTEL);\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_DEVICE_ID],\n+\t\tIAVF_DEV_ID_ADAPTIVE_VF);\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_SUBSYSTEM_VENDOR_ID],\n+\t\tPCI_VENDOR_ID_INTEL);\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_SUBSYSTEM_ID],\n+\t\t   PCI_SUBDEVICE_ID);\n+\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_COMMAND],\n+\t\t   PCI_COMMAND_IO | PCI_COMMAND_MEMORY);\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_CLASS_DEVICE],\n+\t\t   PCI_CLASS_ETHERNET);\n+\tv_cfg[PCI_CLASS_REVISION] = 0x01;\n+\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_STATUS],\n+\t\t\t   PCI_STATUS_CAP_LIST);\n+\n+\tSTORE_LE32((uint32_t *)&v_cfg[PCI_BASE_ADDRESS_0],\n+\t\t   PCI_BASE_ADDRESS_SPACE_MEMORY |\n+\t\t   PCI_BASE_ADDRESS_MEM_TYPE_32\t |\n+\t\t   PCI_BASE_ADDRESS_MEM_PREFETCH);\n+\n+\tSTORE_LE32((uint32_t *)&v_cfg[PCI_BASE_ADDRESS_3],\n+\t\t   PCI_BASE_ADDRESS_SPACE_MEMORY |\n+\t\t   PCI_BASE_ADDRESS_MEM_TYPE_32);\n+\n+\tSTORE_LE16((uint16_t *)&v_cfg[PCI_CAPABILITY_LIST],\n+\t\t\t   0x70);\n+\tSTORE_LE16((uint16_t *)&v_cfg[0x70],\n+\t\t\t   PCI_CAP_ID_MSIX);\n+\n+\tSTORE_LE16((uint16_t *)&v_cfg[0x70 + PCI_MSIX_FLAGS],\n+\t\t\t(IAVF_EMU_MSIX_TABLE_SIZE & PCI_MSIX_FLAGS_QSIZE) |\n+\t\t\tPCI_MSIX_FLAGS_ENABLE);\n+\n+\tSTORE_LE32((uint32_t *)&v_cfg[0x70 + PCI_MSIX_TABLE],\n+\t\t\t   (0x3 & PCI_MSIX_TABLE_BIR));\n+\n+\tSTORE_LE32((uint32_t *)&v_cfg[0x70 + PCI_MSIX_PBA],\n+\t\t\t(0x3 & PCI_MSIX_PBA_BIR) |\n+\t\t\t(0x100 & PCI_MSIX_PBA_OFFSET));\n+\n+\treturn 0;\n+}\n+\n+static inline void\n+iavf_emu_uninit_cfg_space(struct rte_vfio_user_reg_info *vinfo)\n+{\n+\trte_free(vinfo->base);\n+\tvinfo->rw = NULL;\n+\tvinfo->info->size = 0;\n+\tvinfo->fd = -1;\n+}\n+\n+static ssize_t\n+iavf_emu_bar0_rw(struct rte_vfio_user_reg_info *reg, char *buf,\n+\tsize_t count, loff_t pos, bool iswrite)\n+{\n+\tstruct iavf_emudev *dev = (struct iavf_emudev *)reg->priv;\n+\tchar *reg_pos;\n+\n+\tif (!reg->base) {\n+\t\tEMU_IAVF_LOG(ERR, \"BAR 0 does not exist\\n\");\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tif (pos + count > reg->info->size) {\n+\t\tEMU_IAVF_LOG(ERR, \"Access exceeds BAR 0 size\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treg_pos = (char *)reg->base + pos;\n+\n+\tif (!iswrite) {\n+\t\trte_memcpy(buf, reg_pos, count);\n+\t} else {\n+\t\tint tmp;\n+\t\tuint32_t val;\n+\t\tint idx = -1;\n+\n+\t\tif (count != 4)\n+\t\t\treturn -EINVAL;\n+\n+\t\tval = *(uint32_t *)buf;\n+\t\t/* Only handle interrupt enable/disable for now */\n+\t\tif (pos == IAVF_VFINT_DYN_CTL01) {\n+\t\t\ttmp = val & IAVF_VFINT_DYN_CTL01_INTENA_MASK;\n+\t\t\tidx = 0;\n+\t\t} else if ((pos >= IAVF_VFINT_DYN_CTLN1(0)) && pos <=\n+\t\t\tIAVF_VFINT_DYN_CTLN1(RTE_IAVF_EMU_MAX_INTR - 1)) {\n+\t\t\ttmp = val & IAVF_VFINT_DYN_CTLN1_INTENA_MASK;\n+\t\t\tidx = pos - IAVF_VFINT_DYN_CTLN1(0);\n+\t\t\tif (idx % 4)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tidx = idx / 4 + 1;\n+\t\t}\n+\n+\t\tif (idx != -1 &&\n+\t\t\ttmp != dev->intr->info[idx].enable && dev->ready) {\n+\t\t\tdev->intr->info[idx].enable = tmp;\n+\t\t\trte_wmb();\n+\t\t\tdev->ops->lock_dp(dev->edev, 1);\n+\t\t\tdev->ops->update_status(dev->edev);\n+\t\t\tdev->ops->lock_dp(dev->edev, 0);\n+\t\t}\n+\n+\t\trte_memcpy(reg_pos, buf, count);\n+\t}\n+\n+\treturn count;\n+}\n+\n+static int\n+iavf_emu_alloc_reg(struct iavf_emudev *dev)\n+{\n+\tstruct rte_vfio_user_regions *reg = dev->vfio->reg;\n+\tstruct rte_vfio_user_reg_info *vinfo;\n+\tchar shm_str[64];\n+\tuint32_t i;\n+\tint ret;\n+\n+\tfor (i = 0; i < reg->reg_num; i++) {\n+\t\tvinfo = &reg->reg_info[i];\n+\n+\t\tswitch (i) {\n+\t\tcase VFIO_PCI_CONFIG_REGION_INDEX:\n+\t\t\tret = iavf_emu_init_cfg_space(vinfo, dev->numa_node);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t\tbreak;\n+\t\tcase VFIO_PCI_BAR0_REGION_INDEX:\n+\t\tcase VFIO_PCI_BAR3_REGION_INDEX:\n+\t\t\tsprintf(shm_str, \"AVF%d_BAR%d\",\n+\t\t\t\tdev->edev->dev_id, i);\n+\t\t\tvinfo->fd = shm_open(shm_str,\n+\t\t\t\tO_RDWR|O_CREAT, 0700);\n+\t\t\tif (vinfo->fd == -1) {\n+\t\t\t\tEMU_IAVF_LOG(ERR,\n+\t\t\t\t\t\"Failed to open shm for BAR %d\\n\", i);\n+\t\t\t\tgoto exit;\n+\t\t\t}\n+\n+\t\t\tif (ftruncate(vinfo->fd, vinfo->info->size) == -1) {\n+\t\t\t\tEMU_IAVF_LOG(ERR,\n+\t\t\t\t\t\"Failed to ftruncate BAR %d\\n\", i);\n+\t\t\t\tret = -1;\n+\t\t\t\tgoto exit;\n+\t\t\t}\n+\n+\t\t\tvinfo->base = mmap(NULL, vinfo->info->size,\n+\t\t\t\t\tPROT_READ | PROT_WRITE,\n+\t\t\t\t\tMAP_SHARED, vinfo->fd, 0);\n+\t\t\tmemset(vinfo->base, 0, vinfo->info->size);\n+\t\t\tif (vinfo->base == MAP_FAILED) {\n+\t\t\t\tEMU_IAVF_LOG(ERR,\n+\t\t\t\t\t\"Failed to mmap BAR %d\\n\", i);\n+\t\t\t\tret = -1;\n+\t\t\t\tgoto exit;\n+\t\t\t}\n+\t\t\tvinfo->priv = (void *)dev;\n+\t\t\tif (i == VFIO_PCI_BAR0_REGION_INDEX)\n+\t\t\t\tvinfo->rw = iavf_emu_bar0_rw;\n+\t\t\telse\n+\t\t\t\tvinfo->rw = NULL;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tvinfo->base = NULL;\n+\t\t\tvinfo->rw = NULL;\n+\t\t\tvinfo->fd = -1;\n+\t\t\tvinfo->priv = NULL;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+exit:\n+\tfor (;; i--) {\n+\t\tvinfo = &reg->reg_info[i];\n+\n+\t\tif (i == VFIO_PCI_CONFIG_REGION_INDEX)\n+\t\t\tiavf_emu_uninit_cfg_space(vinfo);\n+\n+\t\tif (!vinfo->info->size) {\n+\t\t\tif (!vinfo->base)\n+\t\t\t\tmunmap(vinfo->base, vinfo->info->size);\n+\t\t\tif (vinfo->fd > 0) {\n+\t\t\t\tclose(vinfo->fd);\n+\t\t\t\tsprintf(shm_str, \"AVF%d_BAR%d\",\n+\t\t\t\t\tdev->edev->dev_id, i);\n+\t\t\t\tshm_unlink(shm_str);\n+\t\t\t\tvinfo->fd = -1;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (i == 0)\n+\t\t\tbreak;\n+\t}\n+\treturn ret;\n+}\n+\n+static void\n+iavf_emu_free_reg(struct iavf_emudev *dev)\n+{\n+\tstruct rte_vfio_user_regions *reg = dev->vfio->reg;\n+\tstruct rte_vfio_user_reg_info *vinfo;\n+\tchar shm_str[64];\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < reg->reg_num; i++) {\n+\t\tvinfo = &reg->reg_info[i];\n+\n+\t\tswitch (i) {\n+\t\tcase VFIO_PCI_CONFIG_REGION_INDEX:\n+\t\t\tiavf_emu_uninit_cfg_space(vinfo);\n+\t\t\tbreak;\n+\t\tcase VFIO_PCI_BAR0_REGION_INDEX:\n+\t\t\t/* FALLTHROUGH */\n+\t\tcase VFIO_PCI_BAR3_REGION_INDEX:\n+\t\t\tmunmap(vinfo->base, vinfo->info->size);\n+\t\t\tclose(vinfo->fd);\n+\t\t\tvinfo->fd = -1;\n+\t\t\tsprintf(shm_str, \"AVF%d_BAR%d\",\n+\t\t\t\tdev->edev->dev_id, i);\n+\t\t\tshm_unlink(shm_str);\n+\t\t\tvinfo->info->size = 0;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n static inline struct iavf_emu_sock_list *\n iavf_emu_find_sock_list(char *sock_addr)\n {\n@@ -397,3 +1003,74 @@ iavf_emu_unregister_vfio_user(struct iavf_emudev *dev)\n \n \treturn 0;\n }\n+\n+int\n+iavf_emu_init_vfio_user(struct iavf_emudev *dev)\n+{\n+\tint ret;\n+\tstruct iavf_emu_sock_list *list;\n+\n+\tif (iavf_emu_init_dev(dev)) {\n+\t\tEMU_IAVF_LOG(ERR, \"Emulated iavf dev init failed.\\n\");\n+\t\tret = -1;\n+\t\tgoto exit;\n+\t}\n+\n+\tif (iavf_emu_alloc_reg(dev)) {\n+\t\tEMU_IAVF_LOG(ERR, \"Emulated iavf alloc region failed.\\n\");\n+\t\tret = -1;\n+\t\tgoto err_alloc_reg;\n+\t}\n+\n+\tret = rte_vfio_user_set_dev_info(dev->sock_addr, dev->vfio->dev_info);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set vfio dev info\\n\");\n+\t\tgoto err_set;\n+\t}\n+\n+\tret = rte_vfio_user_set_reg_info(dev->sock_addr, dev->vfio->reg);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set vfio region info\\n\");\n+\t\tgoto err_set;\n+\t}\n+\n+\tret = rte_vfio_user_set_irq_info(dev->sock_addr, dev->vfio->irq);\n+\tif (ret) {\n+\t\tEMU_IAVF_LOG(ERR, \"Failed to set vfio irq info\\n\");\n+\t\tgoto err_set;\n+\t}\n+\n+\tlist = rte_zmalloc_socket(\"list\", sizeof(*list), 0, dev->numa_node);\n+\tlist->emu_dev = dev->edev;\n+\tpthread_mutex_lock(&sock_list_lock);\n+\tTAILQ_INSERT_TAIL(&sock_list, list, next);\n+\tpthread_mutex_unlock(&sock_list_lock);\n+\n+\treturn 0;\n+\n+err_set:\n+\tiavf_emu_free_reg(dev);\n+err_alloc_reg:\n+\tiavf_emu_uninit_dev(dev);\n+exit:\n+\treturn ret;\n+}\n+\n+void\n+iavf_emu_uninit_vfio_user(struct iavf_emudev *dev)\n+{\n+\tiavf_emu_free_reg(dev);\n+\tiavf_emu_uninit_dev(dev);\n+}\n+\n+int\n+iavf_emu_start_vfio_user(struct iavf_emudev *dev)\n+{\n+\tint ret;\n+\n+\tret = rte_vfio_user_start(dev->sock_addr);\n+\tif (ret)\n+\t\tEMU_IAVF_LOG(ERR, \"Start vfio user failed.\\n\");\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/emu/iavf/iavf_vfio_user.h b/drivers/emu/iavf/iavf_vfio_user.h\nindex aa2f3edc87..2ccb04eb48 100644\n--- a/drivers/emu/iavf/iavf_vfio_user.h\n+++ b/drivers/emu/iavf/iavf_vfio_user.h\n@@ -5,12 +5,53 @@\n #ifndef _IAVF_VFIO_USER_H\n #define _IAVF_VFIO_USER_H\n \n+#include <linux/pci_regs.h>\n+\n #include <rte_vfio_user.h>\n \n #include \"iavf_emu_internal.h\"\n \n+#define IAVF_EMU_CFG_SPACE_SIZE 0x100\n+\n+struct iavf_emu_pci_hdr {\n+\tuint16_t vid;\t\t/* Vendor ID */\n+\tuint16_t did;\t\t/* Device ID */\n+\tuint16_t cmd;\t\t/* Command */\n+\tuint16_t status;\t/* Status */\n+\tuint8_t rid;\t\t/* Revision ID */\n+\tuint8_t cc_pi;\t\t/* Program I/F in Class Code*/\n+\tuint8_t cc_sub;\t\t/* Sub-Class Code */\n+\tuint8_t cc_base;\t/* Base Class Code */\n+\tuint8_t cl_size;\t/* Cache Line Size*/\n+\tuint8_t lt_timer;\t/* Latency Timer */\n+\tuint8_t hdr_type;\t/* Header Type */\n+\tuint8_t bist;\t\t/* BIST */\n+\tuint32_t bar[6];\t/* Base Address Registers */\n+\tuint32_t ccp;\t\t/* Cardbus CIC Pointer */\n+\tuint16_t sub_vid;\t/* Subsystem Vendor ID */\n+\tuint16_t sub_sid;\t/* Subsystem ID */\n+\tuint32_t rom;\t\t/* Expansion ROM Base Address */\n+\tuint8_t cap;\t\t/* Capabilities Pointer */\n+\tuint8_t rsvd[7];\t/* Reserved */\n+\tuint8_t intrl;\t\t/* Interrupt Line */\n+\tuint8_t intrp;\t\t/* Interrupt Pin */\n+\tuint8_t min_gnt;\t/* Min_Gnt Register */\n+\tuint8_t max_lat;\t/* Max_Lat Register */\n+} __attribute((packed));\n+\n+struct iavf_emu_cfg_space {\n+\tstruct iavf_emu_pci_hdr hdr;\n+\tuint8_t cfg_non_std[IAVF_EMU_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF];\n+} __attribute((packed));\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+int iavf_emu_init_vfio_user(struct iavf_emudev *dev);\n+\n+void iavf_emu_uninit_vfio_user(struct iavf_emudev *dev);\n+\n+int iavf_emu_start_vfio_user(struct iavf_emudev *dev);\n+\n #endif\ndiff --git a/drivers/emu/iavf/meson.build b/drivers/emu/iavf/meson.build\nindex 4f651258c2..3cab2226b7 100644\n--- a/drivers/emu/iavf/meson.build\n+++ b/drivers/emu/iavf/meson.build\n@@ -1,6 +1,14 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright(c) 2020 Intel Corporation\n \n+librt = cc.find_library('rt', required: false)\n+if not librt.found()\n+\tbuild = false\n+\tsubdir_done()\n+endif\n+\n+ext_deps += librt\n+\n sources = files('iavf_emu.c', 'iavf_vfio_user.c',\n \t'iavf_emudev.c')\n \n",
    "prefixes": [
        "v3",
        "5/8"
    ]
}