get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 118773,
    "url": "http://patchwork.dpdk.org/api/patches/118773/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20221020103656.1068036-4-junfeng.guo@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20221020103656.1068036-4-junfeng.guo@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20221020103656.1068036-4-junfeng.guo@intel.com",
    "date": "2022-10-20T10:36:51",
    "name": "[v6,3/8] net/gve: add support for device initialization",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d4cdc88ac39af86f6a7ceccbd565dc5c061336d1",
    "submitter": {
        "id": 1785,
        "url": "http://patchwork.dpdk.org/api/people/1785/?format=api",
        "name": "Junfeng Guo",
        "email": "junfeng.guo@intel.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patchwork.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20221020103656.1068036-4-junfeng.guo@intel.com/mbox/",
    "series": [
        {
            "id": 25340,
            "url": "http://patchwork.dpdk.org/api/series/25340/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=25340",
            "date": "2022-10-20T10:36:48",
            "name": "introduce GVE PMD",
            "version": 6,
            "mbox": "http://patchwork.dpdk.org/series/25340/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/118773/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/118773/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 D81A6A0581;\n\tThu, 20 Oct 2022 12:38:51 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 485BB42D2C;\n\tThu, 20 Oct 2022 12:38:43 +0200 (CEST)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n by mails.dpdk.org (Postfix) with ESMTP id 355D142D19\n for <dev@dpdk.org>; Thu, 20 Oct 2022 12:38:41 +0200 (CEST)",
            "from fmsmga004.fm.intel.com ([10.253.24.48])\n by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 20 Oct 2022 03:38:40 -0700",
            "from dpdk-jf-ntb-one.sh.intel.com ([10.67.111.104])\n by fmsmga004.fm.intel.com with ESMTP; 20 Oct 2022 03:38:37 -0700"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1666262321; x=1697798321;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=1vIq/ZbMV4+19I93++3ZNogwHAAs8m2KmJtViGewacU=;\n b=Z9WDRVzJYB7nXgE5qKVDE7MumE0RnYRTfJ5gDa8/vohNA3zHiJsMUG3v\n j9XnGZA46zjJYNPJj00RsCpclwLzoDhlp5EsVYg7rDYvmrcOgiw3okDSV\n 6UFMILSnwR64s0LmtlYxUzLQ1v+cqVcnyozdp6P/kfvecHPrINAOKw6bF\n 2p8pS0aNfD4AM+oF3ofkRKb2thiis55ysg0B4LCuKV0FULNgDJdTP5QDP\n oPW7I/0YmiLkZ9LTD5n3IZPHjHXqHBInuqvrmk4h/Z4HZj0l975SR+TNR\n zHuVYoJmRYHkjrIvFLjYs1MMmN8StOYuq8RSbWyXbBefyDnDIiE8JPnLf w==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6500,9779,10505\"; a=\"308354891\"",
            "E=Sophos;i=\"5.95,198,1661842800\"; d=\"scan'208\";a=\"308354891\"",
            "E=McAfee;i=\"6500,9779,10505\"; a=\"698582870\"",
            "E=Sophos;i=\"5.95,198,1661842800\"; d=\"scan'208\";a=\"698582870\""
        ],
        "X-ExtLoop1": "1",
        "From": "Junfeng Guo <junfeng.guo@intel.com>",
        "To": "qi.z.zhang@intel.com, jingjing.wu@intel.com, ferruh.yigit@xilinx.com,\n beilei.xing@intel.com",
        "Cc": "dev@dpdk.org, xiaoyun.li@intel.com, awogbemila@google.com,\n bruce.richardson@intel.com, hemant.agrawal@nxp.com,\n stephen@networkplumber.org, chenbo.xia@intel.com, helin.zhang@intel.com,\n Junfeng Guo <junfeng.guo@intel.com>, Haiyue Wang <haiyue.wang@intel.com>",
        "Subject": "[PATCH v6 3/8] net/gve: add support for device initialization",
        "Date": "Thu, 20 Oct 2022 18:36:51 +0800",
        "Message-Id": "<20221020103656.1068036-4-junfeng.guo@intel.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20221020103656.1068036-1-junfeng.guo@intel.com>",
        "References": "<20221010101757.878317-2-junfeng.guo@intel.com>\n <20221020103656.1068036-1-junfeng.guo@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "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"
    },
    "content": "Support device init and add following devops skeleton:\n - dev_configure\n - dev_start\n - dev_stop\n - dev_close\n\nNote that build system (including doc) is also added in this patch.\n\nSigned-off-by: Haiyue Wang <haiyue.wang@intel.com>\nSigned-off-by: Xiaoyun Li <xiaoyun.li@intel.com>\nSigned-off-by: Junfeng Guo <junfeng.guo@intel.com>\n---\n MAINTAINERS                            |   6 +\n doc/guides/nics/features/gve.ini       |  10 +\n doc/guides/nics/gve.rst                |  68 +++++\n doc/guides/nics/index.rst              |   1 +\n doc/guides/rel_notes/release_22_11.rst |   5 +\n drivers/net/gve/base/gve_adminq.c      |   1 +\n drivers/net/gve/gve_ethdev.c           | 371 +++++++++++++++++++++++++\n drivers/net/gve/gve_ethdev.h           | 225 +++++++++++++++\n drivers/net/gve/gve_logs.h             |  14 +\n drivers/net/gve/meson.build            |  14 +\n drivers/net/gve/version.map            |   3 +\n drivers/net/meson.build                |   1 +\n 12 files changed, 719 insertions(+)\n create mode 100644 doc/guides/nics/features/gve.ini\n create mode 100644 doc/guides/nics/gve.rst\n create mode 100644 drivers/net/gve/gve_ethdev.c\n create mode 100644 drivers/net/gve/gve_ethdev.h\n create mode 100644 drivers/net/gve/gve_logs.h\n create mode 100644 drivers/net/gve/meson.build\n create mode 100644 drivers/net/gve/version.map",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 92b381bc30..2d06a76efe 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -697,6 +697,12 @@ F: drivers/net/enic/\n F: doc/guides/nics/enic.rst\n F: doc/guides/nics/features/enic.ini\n \n+Google Virtual Ethernet\n+M: Junfeng Guo <junfeng.guo@intel.com>\n+F: drivers/net/gve/\n+F: doc/guides/nics/gve.rst\n+F: doc/guides/nics/features/gve.ini\n+\n Hisilicon hns3\n M: Dongdong Liu <liudongdong3@huawei.com>\n M: Yisen Zhuang <yisen.zhuang@huawei.com>\ndiff --git a/doc/guides/nics/features/gve.ini b/doc/guides/nics/features/gve.ini\nnew file mode 100644\nindex 0000000000..44aec28009\n--- /dev/null\n+++ b/doc/guides/nics/features/gve.ini\n@@ -0,0 +1,10 @@\n+;\n+; Supported features of the Google Virtual Ethernet 'gve' poll mode driver.\n+;\n+; Refer to default.ini for the full list of available PMD features.\n+;\n+[Features]\n+Linux                = Y\n+x86-32               = Y\n+x86-64               = Y\n+Usage doc            = Y\ndiff --git a/doc/guides/nics/gve.rst b/doc/guides/nics/gve.rst\nnew file mode 100644\nindex 0000000000..703fbcc5de\n--- /dev/null\n+++ b/doc/guides/nics/gve.rst\n@@ -0,0 +1,68 @@\n+..  SPDX-License-Identifier: BSD-3-Clause\n+    Copyright(C) 2022 Intel Corporation.\n+\n+GVE poll mode driver\n+=======================\n+\n+The GVE PMD (**librte_net_gve**) provides poll mode driver support for\n+Google Virtual Ethernet device (also called as gVNIC).\n+\n+gVNIC is the standard virtual ethernet interface on Google Cloud Platform (GCP),\n+which is one of the multiple virtual interfaces from those leading CSP\n+customers in the world.\n+\n+Please refer to https://cloud.google.com/compute/docs/networking/using-gvnic\n+for the device description.\n+\n+Having a well maintained/optimized gve PMD on DPDK community can help those\n+cloud instance consumers with better experience of performance, maintenance\n+who wants to run their own VNFs on GCP.\n+\n+The base code is under MIT license and based on GVE kernel driver v1.3.0.\n+GVE base code files are:\n+\n+- gve_adminq.h\n+- gve_adminq.c\n+- gve_desc.h\n+- gve_desc_dqo.h\n+- gve_register.h\n+- gve.h\n+\n+Please refer to https://github.com/GoogleCloudPlatform/compute-virtual-ethernet-linux/tree/v1.3.0/google/gve\n+to find the original base code.\n+\n+GVE has 3 queue formats:\n+\n+- GQI_QPL - GQI with queue page list\n+- GQI_RDA - GQI with raw DMA addressing\n+- DQO_RDA - DQO with raw DMA addressing\n+\n+GQI_QPL queue format is queue page list mode. Driver needs to allocate\n+memory and register this memory as a Queue Page List (QPL) in hardware\n+(Google Hypervisor/GVE Backend) first. Each queue has its own QPL.\n+Then Tx needs to copy packets to QPL memory and put this packet's offset\n+in the QPL memory into hardware descriptors so that hardware can get the\n+packets data. And Rx needs to read descriptors of offset in QPL to get\n+QPL address and copy packets from the address to get real packets data.\n+\n+GQI_RDA queue format works like usual NICs that driver can put packets'\n+physical address into hardware descriptors.\n+\n+DQO_RDA queue format has submission and completion queue pair for each\n+Tx/Rx queue. And similar as GQI_RDA, driver can put packets' physical\n+address into hardware descriptors.\n+\n+Please refer to https://www.kernel.org/doc/html/latest/networking/device_drivers/ethernet/google/gve.html\n+to get more information about GVE queue formats.\n+\n+Features and Limitations\n+------------------------\n+\n+In this release, the GVE PMD provides the basic functionality of packet\n+reception and transmission.\n+\n+Currently, only GQI_QPL and GQI_RDA queue format are supported in PMD.\n+Jumbo Frame is not supported in PMD for now. It'll be added in the future\n+DPDK release.\n+Also, only GQI_QPL queue format is in use on GCP since GQI_RDA hasn't been\n+released in production.\ndiff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst\nindex 32c7544968..4d40ea29a3 100644\n--- a/doc/guides/nics/index.rst\n+++ b/doc/guides/nics/index.rst\n@@ -29,6 +29,7 @@ Network Interface Controller Drivers\n     enetfec\n     enic\n     fm10k\n+    gve\n     hinic\n     hns3\n     i40e\ndiff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst\nindex 1c3daf141d..715013fa35 100644\n--- a/doc/guides/rel_notes/release_22_11.rst\n+++ b/doc/guides/rel_notes/release_22_11.rst\n@@ -140,6 +140,11 @@ New Features\n \n   * Made compatible with libbpf v0.8.0 (when used with libxdp).\n \n+* **Added GVE net PMD**\n+\n+  * Added the new ``gve`` net driver for Google Virtual Ethernet devices.\n+  * See the :doc:`../nics/gve` NIC guide for more details on this new driver.\n+\n * **Updated AMD Pensando ionic driver.**\n \n   Updated the ionic PMD with new features and improvements, including:\ndiff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c\nindex 2344100f1a..ceafa05286 100644\n--- a/drivers/net/gve/base/gve_adminq.c\n+++ b/drivers/net/gve/base/gve_adminq.c\n@@ -5,6 +5,7 @@\n  * Copyright(C) 2022 Intel Corporation\n  */\n \n+#include \"../gve_ethdev.h\"\n #include \"gve_adminq.h\"\n #include \"gve_register.h\"\n \ndiff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c\nnew file mode 100644\nindex 0000000000..f8ff3b1923\n--- /dev/null\n+++ b/drivers/net/gve/gve_ethdev.c\n@@ -0,0 +1,371 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2022 Intel Corporation\n+ */\n+#include <linux/pci_regs.h>\n+\n+#include \"gve_ethdev.h\"\n+#include \"base/gve_adminq.h\"\n+#include \"base/gve_register.h\"\n+\n+const char gve_version_str[] = GVE_VERSION;\n+static const char gve_version_prefix[] = GVE_VERSION_PREFIX;\n+\n+static void\n+gve_write_version(uint8_t *driver_version_register)\n+{\n+\tconst char *c = gve_version_prefix;\n+\n+\twhile (*c) {\n+\t\twriteb(*c, driver_version_register);\n+\t\tc++;\n+\t}\n+\n+\tc = gve_version_str;\n+\twhile (*c) {\n+\t\twriteb(*c, driver_version_register);\n+\t\tc++;\n+\t}\n+\twriteb('\\n', driver_version_register);\n+}\n+\n+static int\n+gve_dev_configure(__rte_unused struct rte_eth_dev *dev)\n+{\n+\treturn 0;\n+}\n+\n+static int\n+gve_dev_start(struct rte_eth_dev *dev)\n+{\n+\tdev->data->dev_started = 1;\n+\n+\treturn 0;\n+}\n+\n+static int\n+gve_dev_stop(struct rte_eth_dev *dev)\n+{\n+\tdev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;\n+\tdev->data->dev_started = 0;\n+\n+\treturn 0;\n+}\n+\n+static int\n+gve_dev_close(struct rte_eth_dev *dev)\n+{\n+\tint err = 0;\n+\n+\tif (dev->data->dev_started) {\n+\t\terr = gve_dev_stop(dev);\n+\t\tif (err != 0)\n+\t\t\tPMD_DRV_LOG(ERR, \"Failed to stop dev.\");\n+\t}\n+\n+\treturn err;\n+}\n+\n+static const struct eth_dev_ops gve_eth_dev_ops = {\n+\t.dev_configure        = gve_dev_configure,\n+\t.dev_start            = gve_dev_start,\n+\t.dev_stop             = gve_dev_stop,\n+\t.dev_close            = gve_dev_close,\n+};\n+\n+static void\n+gve_free_counter_array(struct gve_priv *priv)\n+{\n+\trte_memzone_free(priv->cnt_array_mz);\n+\tpriv->cnt_array = NULL;\n+}\n+\n+static void\n+gve_free_irq_db(struct gve_priv *priv)\n+{\n+\trte_memzone_free(priv->irq_dbs_mz);\n+\tpriv->irq_dbs = NULL;\n+}\n+\n+static void\n+gve_teardown_device_resources(struct gve_priv *priv)\n+{\n+\tint err;\n+\n+\t/* Tell device its resources are being freed */\n+\tif (gve_get_device_resources_ok(priv)) {\n+\t\terr = gve_adminq_deconfigure_device_resources(priv);\n+\t\tif (err)\n+\t\t\tPMD_DRV_LOG(ERR, \"Could not deconfigure device resources: err=%d\", err);\n+\t}\n+\tgve_free_counter_array(priv);\n+\tgve_free_irq_db(priv);\n+\tgve_clear_device_resources_ok(priv);\n+}\n+\n+static uint8_t\n+pci_dev_find_capability(struct rte_pci_device *pdev, int cap)\n+{\n+\tuint8_t pos, id;\n+\tuint16_t ent;\n+\tint loops;\n+\tint ret;\n+\n+\tret = rte_pci_read_config(pdev, &pos, sizeof(pos), PCI_CAPABILITY_LIST);\n+\tif (ret != sizeof(pos))\n+\t\treturn 0;\n+\n+\tloops = (PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF) / PCI_CAP_SIZEOF;\n+\n+\twhile (pos && loops--) {\n+\t\tret = rte_pci_read_config(pdev, &ent, sizeof(ent), pos);\n+\t\tif (ret != sizeof(ent))\n+\t\t\treturn 0;\n+\n+\t\tid = ent & 0xff;\n+\t\tif (id == 0xff)\n+\t\t\tbreak;\n+\n+\t\tif (id == cap)\n+\t\t\treturn pos;\n+\n+\t\tpos = (ent >> 8);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+pci_dev_msix_vec_count(struct rte_pci_device *pdev)\n+{\n+\tuint8_t msix_cap = pci_dev_find_capability(pdev, PCI_CAP_ID_MSIX);\n+\tuint16_t control;\n+\tint ret;\n+\n+\tif (!msix_cap)\n+\t\treturn 0;\n+\n+\tret = rte_pci_read_config(pdev, &control, sizeof(control), msix_cap + PCI_MSIX_FLAGS);\n+\tif (ret != sizeof(control))\n+\t\treturn 0;\n+\n+\treturn (control & PCI_MSIX_FLAGS_QSIZE) + 1;\n+}\n+\n+static int\n+gve_setup_device_resources(struct gve_priv *priv)\n+{\n+\tchar z_name[RTE_MEMZONE_NAMESIZE];\n+\tconst struct rte_memzone *mz;\n+\tint err = 0;\n+\n+\tsnprintf(z_name, sizeof(z_name), \"gve_%s_cnt_arr\", priv->pci_dev->device.name);\n+\tmz = rte_memzone_reserve_aligned(z_name,\n+\t\t\t\t\t priv->num_event_counters * sizeof(*priv->cnt_array),\n+\t\t\t\t\t rte_socket_id(), RTE_MEMZONE_IOVA_CONTIG,\n+\t\t\t\t\t PAGE_SIZE);\n+\tif (mz == NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"Could not alloc memzone for count array\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tpriv->cnt_array = (rte_be32_t *)mz->addr;\n+\tpriv->cnt_array_mz = mz;\n+\n+\tsnprintf(z_name, sizeof(z_name), \"gve_%s_irqmz\", priv->pci_dev->device.name);\n+\tmz = rte_memzone_reserve_aligned(z_name,\n+\t\t\t\t\t sizeof(*priv->irq_dbs) * (priv->num_ntfy_blks),\n+\t\t\t\t\t rte_socket_id(), RTE_MEMZONE_IOVA_CONTIG,\n+\t\t\t\t\t PAGE_SIZE);\n+\tif (mz == NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"Could not alloc memzone for irq_dbs\");\n+\t\terr = -ENOMEM;\n+\t\tgoto free_cnt_array;\n+\t}\n+\tpriv->irq_dbs = (struct gve_irq_db *)mz->addr;\n+\tpriv->irq_dbs_mz = mz;\n+\n+\terr = gve_adminq_configure_device_resources(priv,\n+\t\t\t\t\t\t    priv->cnt_array_mz->iova,\n+\t\t\t\t\t\t    priv->num_event_counters,\n+\t\t\t\t\t\t    priv->irq_dbs_mz->iova,\n+\t\t\t\t\t\t    priv->num_ntfy_blks);\n+\tif (unlikely(err)) {\n+\t\tPMD_DRV_LOG(ERR, \"Could not config device resources: err=%d\", err);\n+\t\tgoto free_irq_dbs;\n+\t}\n+\treturn 0;\n+\n+free_irq_dbs:\n+\tgve_free_irq_db(priv);\n+free_cnt_array:\n+\tgve_free_counter_array(priv);\n+\n+\treturn err;\n+}\n+\n+static int\n+gve_init_priv(struct gve_priv *priv, bool skip_describe_device)\n+{\n+\tint num_ntfy;\n+\tint err;\n+\n+\t/* Set up the adminq */\n+\terr = gve_adminq_alloc(priv);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc admin queue: err=%d\", err);\n+\t\treturn err;\n+\t}\n+\n+\tif (skip_describe_device)\n+\t\tgoto setup_device;\n+\n+\t/* Get the initial information we need from the device */\n+\terr = gve_adminq_describe_device(priv);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Could not get device information: err=%d\", err);\n+\t\tgoto free_adminq;\n+\t}\n+\n+\tnum_ntfy = pci_dev_msix_vec_count(priv->pci_dev);\n+\tif (num_ntfy <= 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Could not count MSI-x vectors\");\n+\t\terr = -EIO;\n+\t\tgoto free_adminq;\n+\t} else if (num_ntfy < GVE_MIN_MSIX) {\n+\t\tPMD_DRV_LOG(ERR, \"GVE needs at least %d MSI-x vectors, but only has %d\",\n+\t\t\t    GVE_MIN_MSIX, num_ntfy);\n+\t\terr = -EINVAL;\n+\t\tgoto free_adminq;\n+\t}\n+\n+\tpriv->num_registered_pages = 0;\n+\n+\t/* gvnic has one Notification Block per MSI-x vector, except for the\n+\t * management vector\n+\t */\n+\tpriv->num_ntfy_blks = (num_ntfy - 1) & ~0x1;\n+\tpriv->mgmt_msix_idx = priv->num_ntfy_blks;\n+\n+\tpriv->max_nb_txq = RTE_MIN(priv->max_nb_txq, priv->num_ntfy_blks / 2);\n+\tpriv->max_nb_rxq = RTE_MIN(priv->max_nb_rxq, priv->num_ntfy_blks / 2);\n+\n+\tif (priv->default_num_queues > 0) {\n+\t\tpriv->max_nb_txq = RTE_MIN(priv->default_num_queues, priv->max_nb_txq);\n+\t\tpriv->max_nb_rxq = RTE_MIN(priv->default_num_queues, priv->max_nb_rxq);\n+\t}\n+\n+\tPMD_DRV_LOG(INFO, \"Max TX queues %d, Max RX queues %d\",\n+\t\t    priv->max_nb_txq, priv->max_nb_rxq);\n+\n+setup_device:\n+\terr = gve_setup_device_resources(priv);\n+\tif (!err)\n+\t\treturn 0;\n+free_adminq:\n+\tgve_adminq_free(priv);\n+\treturn err;\n+}\n+\n+static void\n+gve_teardown_priv_resources(struct gve_priv *priv)\n+{\n+\tgve_teardown_device_resources(priv);\n+\tgve_adminq_free(priv);\n+}\n+\n+static int\n+gve_dev_init(struct rte_eth_dev *eth_dev)\n+{\n+\tstruct gve_priv *priv = eth_dev->data->dev_private;\n+\tint max_tx_queues, max_rx_queues;\n+\tstruct rte_pci_device *pci_dev;\n+\tstruct gve_registers *reg_bar;\n+\trte_be32_t *db_bar;\n+\tint err;\n+\n+\teth_dev->dev_ops = &gve_eth_dev_ops;\n+\n+\tif (rte_eal_process_type() != RTE_PROC_PRIMARY)\n+\t\treturn 0;\n+\n+\tpci_dev = RTE_DEV_TO_PCI(eth_dev->device);\n+\n+\treg_bar = pci_dev->mem_resource[GVE_REG_BAR].addr;\n+\tif (!reg_bar) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to map pci bar!\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tdb_bar = pci_dev->mem_resource[GVE_DB_BAR].addr;\n+\tif (!db_bar) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to map doorbell bar!\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tgve_write_version(&reg_bar->driver_version);\n+\t/* Get max queues to alloc etherdev */\n+\tmax_tx_queues = ioread32be(&reg_bar->max_tx_queues);\n+\tmax_rx_queues = ioread32be(&reg_bar->max_rx_queues);\n+\n+\tpriv->reg_bar0 = reg_bar;\n+\tpriv->db_bar2 = db_bar;\n+\tpriv->pci_dev = pci_dev;\n+\tpriv->state_flags = 0x0;\n+\n+\tpriv->max_nb_txq = max_tx_queues;\n+\tpriv->max_nb_rxq = max_rx_queues;\n+\n+\terr = gve_init_priv(priv, false);\n+\tif (err)\n+\t\treturn err;\n+\n+\teth_dev->data->mac_addrs = rte_zmalloc(\"gve_mac\", sizeof(struct rte_ether_addr), 0);\n+\tif (!eth_dev->data->mac_addrs) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to allocate memory to store mac address\");\n+\t\treturn -ENOMEM;\n+\t}\n+\trte_ether_addr_copy(&priv->dev_addr, eth_dev->data->mac_addrs);\n+\n+\treturn 0;\n+}\n+\n+static int\n+gve_dev_uninit(struct rte_eth_dev *eth_dev)\n+{\n+\tstruct gve_priv *priv = eth_dev->data->dev_private;\n+\n+\tgve_teardown_priv_resources(priv);\n+\n+\teth_dev->data->mac_addrs = NULL;\n+\n+\treturn 0;\n+}\n+\n+static int\n+gve_pci_probe(__rte_unused struct rte_pci_driver *pci_drv,\n+\t      struct rte_pci_device *pci_dev)\n+{\n+\treturn rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct gve_priv), gve_dev_init);\n+}\n+\n+static int\n+gve_pci_remove(struct rte_pci_device *pci_dev)\n+{\n+\treturn rte_eth_dev_pci_generic_remove(pci_dev, gve_dev_uninit);\n+}\n+\n+static const struct rte_pci_id pci_id_gve_map[] = {\n+\t{ RTE_PCI_DEVICE(GOOGLE_VENDOR_ID, GVE_DEV_ID) },\n+\t{ .device_id = 0 },\n+};\n+\n+static struct rte_pci_driver rte_gve_pmd = {\n+\t.id_table = pci_id_gve_map,\n+\t.drv_flags = RTE_PCI_DRV_NEED_MAPPING,\n+\t.probe = gve_pci_probe,\n+\t.remove = gve_pci_remove,\n+};\n+\n+RTE_PMD_REGISTER_PCI(net_gve, rte_gve_pmd);\n+RTE_PMD_REGISTER_PCI_TABLE(net_gve, pci_id_gve_map);\n+RTE_PMD_REGISTER_KMOD_DEP(net_gve, \"* igb_uio | vfio-pci\");\n+RTE_LOG_REGISTER_SUFFIX(gve_logtype_driver, driver, NOTICE);\ndiff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h\nnew file mode 100644\nindex 0000000000..2ac2a46ac1\n--- /dev/null\n+++ b/drivers/net/gve/gve_ethdev.h\n@@ -0,0 +1,225 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2022 Intel Corporation\n+ */\n+\n+#ifndef _GVE_ETHDEV_H_\n+#define _GVE_ETHDEV_H_\n+\n+#include <ethdev_driver.h>\n+#include <ethdev_pci.h>\n+#include <rte_ether.h>\n+\n+#include \"base/gve.h\"\n+\n+#define GVE_DEFAULT_RX_FREE_THRESH  512\n+#define GVE_DEFAULT_TX_FREE_THRESH  256\n+#define GVE_TX_MAX_FREE_SZ          512\n+\n+#define GVE_MIN_BUF_SIZE\t    1024\n+#define GVE_MAX_RX_PKTLEN\t    65535\n+\n+/* A list of pages registered with the device during setup and used by a queue\n+ * as buffers\n+ */\n+struct gve_queue_page_list {\n+\tuint32_t id; /* unique id */\n+\tuint32_t num_entries;\n+\tdma_addr_t *page_buses; /* the dma addrs of the pages */\n+\tconst struct rte_memzone *mz;\n+};\n+\n+/* A TX desc ring entry */\n+union gve_tx_desc {\n+\tstruct gve_tx_pkt_desc pkt; /* first desc for a packet */\n+\tstruct gve_tx_seg_desc seg; /* subsequent descs for a packet */\n+};\n+\n+struct gve_tx_queue {\n+\tvolatile union gve_tx_desc *tx_desc_ring;\n+\tconst struct rte_memzone *mz;\n+\tuint64_t tx_ring_phys_addr;\n+\n+\tuint16_t nb_tx_desc;\n+\n+\t/* Only valid for DQO_QPL queue format */\n+\tstruct gve_queue_page_list *qpl;\n+\n+\tuint16_t port_id;\n+\tuint16_t queue_id;\n+\n+\tuint16_t ntfy_id;\n+\tvolatile rte_be32_t *ntfy_addr;\n+\n+\tstruct gve_priv *hw;\n+\tconst struct rte_memzone *qres_mz;\n+\tstruct gve_queue_resources *qres;\n+\n+\t/* Only valid for DQO_RDA queue format */\n+\tstruct gve_tx_queue *complq;\n+};\n+\n+struct gve_rx_queue {\n+\tvolatile struct gve_rx_desc *rx_desc_ring;\n+\tvolatile union gve_rx_data_slot *rx_data_ring;\n+\tconst struct rte_memzone *mz;\n+\tconst struct rte_memzone *data_mz;\n+\tuint64_t rx_ring_phys_addr;\n+\n+\tuint16_t nb_rx_desc;\n+\n+\tvolatile rte_be32_t *ntfy_addr;\n+\n+\t/* only valid for GQI_QPL queue format */\n+\tstruct gve_queue_page_list *qpl;\n+\n+\tstruct gve_priv *hw;\n+\tconst struct rte_memzone *qres_mz;\n+\tstruct gve_queue_resources *qres;\n+\n+\tuint16_t port_id;\n+\tuint16_t queue_id;\n+\tuint16_t ntfy_id;\n+\tuint16_t rx_buf_len;\n+\n+\t/* Only valid for DQO_RDA queue format */\n+\tstruct gve_rx_queue *bufq;\n+};\n+\n+struct gve_priv {\n+\tstruct gve_irq_db *irq_dbs; /* array of num_ntfy_blks */\n+\tconst struct rte_memzone *irq_dbs_mz;\n+\tuint32_t mgmt_msix_idx;\n+\trte_be32_t *cnt_array; /* array of num_event_counters */\n+\tconst struct rte_memzone *cnt_array_mz;\n+\n+\tuint16_t num_event_counters;\n+\tuint16_t tx_desc_cnt; /* txq size */\n+\tuint16_t rx_desc_cnt; /* rxq size */\n+\tuint16_t tx_pages_per_qpl; /* tx buffer length */\n+\tuint16_t rx_data_slot_cnt; /* rx buffer length */\n+\n+\t/* Only valid for DQO_RDA queue format */\n+\tuint16_t tx_compq_size; /* tx completion queue size */\n+\tuint16_t rx_bufq_size; /* rx buff queue size */\n+\n+\tuint64_t max_registered_pages;\n+\tuint64_t num_registered_pages; /* num pages registered with NIC */\n+\tuint16_t default_num_queues; /* default num queues to set up */\n+\tenum gve_queue_format queue_format; /* see enum gve_queue_format */\n+\tuint8_t enable_rsc;\n+\n+\tuint16_t max_nb_txq;\n+\tuint16_t max_nb_rxq;\n+\tuint32_t num_ntfy_blks; /* spilt between TX and RX so must be even */\n+\n+\tstruct gve_registers __iomem *reg_bar0; /* see gve_register.h */\n+\trte_be32_t __iomem *db_bar2; /* \"array\" of doorbells */\n+\tstruct rte_pci_device *pci_dev;\n+\n+\t/* Admin queue - see gve_adminq.h*/\n+\tunion gve_adminq_command *adminq;\n+\tstruct gve_dma_mem adminq_dma_mem;\n+\tuint32_t adminq_mask; /* masks prod_cnt to adminq size */\n+\tuint32_t adminq_prod_cnt; /* free-running count of AQ cmds executed */\n+\tuint32_t adminq_cmd_fail; /* free-running count of AQ cmds failed */\n+\tuint32_t adminq_timeouts; /* free-running count of AQ cmds timeouts */\n+\t/* free-running count of per AQ cmd executed */\n+\tuint32_t adminq_describe_device_cnt;\n+\tuint32_t adminq_cfg_device_resources_cnt;\n+\tuint32_t adminq_register_page_list_cnt;\n+\tuint32_t adminq_unregister_page_list_cnt;\n+\tuint32_t adminq_create_tx_queue_cnt;\n+\tuint32_t adminq_create_rx_queue_cnt;\n+\tuint32_t adminq_destroy_tx_queue_cnt;\n+\tuint32_t adminq_destroy_rx_queue_cnt;\n+\tuint32_t adminq_dcfg_device_resources_cnt;\n+\tuint32_t adminq_set_driver_parameter_cnt;\n+\tuint32_t adminq_report_stats_cnt;\n+\tuint32_t adminq_report_link_speed_cnt;\n+\tuint32_t adminq_get_ptype_map_cnt;\n+\n+\tvolatile uint32_t state_flags;\n+\n+\t/* Gvnic device link speed from hypervisor. */\n+\tuint64_t link_speed;\n+\n+\tuint16_t max_mtu;\n+\tstruct rte_ether_addr dev_addr; /* mac address */\n+\n+\tstruct gve_queue_page_list *qpl;\n+\n+\tstruct gve_tx_queue **txqs;\n+\tstruct gve_rx_queue **rxqs;\n+};\n+\n+static inline bool\n+gve_is_gqi(struct gve_priv *priv)\n+{\n+\treturn priv->queue_format == GVE_GQI_RDA_FORMAT ||\n+\t\tpriv->queue_format == GVE_GQI_QPL_FORMAT;\n+}\n+\n+static inline bool\n+gve_get_admin_queue_ok(struct gve_priv *priv)\n+{\n+\treturn !!rte_bit_relaxed_get32(GVE_PRIV_FLAGS_ADMIN_QUEUE_OK,\n+\t\t\t\t       &priv->state_flags);\n+}\n+\n+static inline void\n+gve_set_admin_queue_ok(struct gve_priv *priv)\n+{\n+\trte_bit_relaxed_set32(GVE_PRIV_FLAGS_ADMIN_QUEUE_OK,\n+\t\t\t      &priv->state_flags);\n+}\n+\n+static inline void\n+gve_clear_admin_queue_ok(struct gve_priv *priv)\n+{\n+\trte_bit_relaxed_clear32(GVE_PRIV_FLAGS_ADMIN_QUEUE_OK,\n+\t\t\t\t&priv->state_flags);\n+}\n+\n+static inline bool\n+gve_get_device_resources_ok(struct gve_priv *priv)\n+{\n+\treturn !!rte_bit_relaxed_get32(GVE_PRIV_FLAGS_DEVICE_RESOURCES_OK,\n+\t\t\t\t       &priv->state_flags);\n+}\n+\n+static inline void\n+gve_set_device_resources_ok(struct gve_priv *priv)\n+{\n+\trte_bit_relaxed_set32(GVE_PRIV_FLAGS_DEVICE_RESOURCES_OK,\n+\t\t\t      &priv->state_flags);\n+}\n+\n+static inline void\n+gve_clear_device_resources_ok(struct gve_priv *priv)\n+{\n+\trte_bit_relaxed_clear32(GVE_PRIV_FLAGS_DEVICE_RESOURCES_OK,\n+\t\t\t\t&priv->state_flags);\n+}\n+\n+static inline bool\n+gve_get_device_rings_ok(struct gve_priv *priv)\n+{\n+\treturn !!rte_bit_relaxed_get32(GVE_PRIV_FLAGS_DEVICE_RINGS_OK,\n+\t\t\t\t       &priv->state_flags);\n+}\n+\n+static inline void\n+gve_set_device_rings_ok(struct gve_priv *priv)\n+{\n+\trte_bit_relaxed_set32(GVE_PRIV_FLAGS_DEVICE_RINGS_OK,\n+\t\t\t      &priv->state_flags);\n+}\n+\n+static inline void\n+gve_clear_device_rings_ok(struct gve_priv *priv)\n+{\n+\trte_bit_relaxed_clear32(GVE_PRIV_FLAGS_DEVICE_RINGS_OK,\n+\t\t\t\t&priv->state_flags);\n+}\n+\n+#endif /* _GVE_ETHDEV_H_ */\ndiff --git a/drivers/net/gve/gve_logs.h b/drivers/net/gve/gve_logs.h\nnew file mode 100644\nindex 0000000000..0d02da46e1\n--- /dev/null\n+++ b/drivers/net/gve/gve_logs.h\n@@ -0,0 +1,14 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2022 Intel Corporation\n+ */\n+\n+#ifndef _GVE_LOGS_H_\n+#define _GVE_LOGS_H_\n+\n+extern int gve_logtype_driver;\n+\n+#define PMD_DRV_LOG(level, fmt, args...) \\\n+\trte_log(RTE_LOG_ ## level, gve_logtype_driver, \"%s(): \" fmt \"\\n\", \\\n+\t\t__func__, ## args)\n+\n+#endif\ndiff --git a/drivers/net/gve/meson.build b/drivers/net/gve/meson.build\nnew file mode 100644\nindex 0000000000..d8ec64b3a3\n--- /dev/null\n+++ b/drivers/net/gve/meson.build\n@@ -0,0 +1,14 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(C) 2022 Intel Corporation\n+\n+if is_windows\n+    build = false\n+    reason = 'not supported on Windows'\n+    subdir_done()\n+endif\n+\n+sources = files(\n+        'base/gve_adminq.c',\n+        'gve_ethdev.c',\n+)\n+includes += include_directories('base')\ndiff --git a/drivers/net/gve/version.map b/drivers/net/gve/version.map\nnew file mode 100644\nindex 0000000000..c2e0723b4c\n--- /dev/null\n+++ b/drivers/net/gve/version.map\n@@ -0,0 +1,3 @@\n+DPDK_22 {\n+\tlocal: *;\n+};\ndiff --git a/drivers/net/meson.build b/drivers/net/meson.build\nindex 35bfa78dee..355dbd07e9 100644\n--- a/drivers/net/meson.build\n+++ b/drivers/net/meson.build\n@@ -23,6 +23,7 @@ drivers = [\n         'enic',\n         'failsafe',\n         'fm10k',\n+        'gve',\n         'hinic',\n         'hns3',\n         'i40e',\n",
    "prefixes": [
        "v6",
        "3/8"
    ]
}