get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 114453,
    "url": "http://patchwork.dpdk.org/api/patches/114453/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20220729193042.2764633-4-xiaoyun.li@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": "<20220729193042.2764633-4-xiaoyun.li@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220729193042.2764633-4-xiaoyun.li@intel.com",
    "date": "2022-07-29T19:30:35",
    "name": "[03/10] net/gve: support device initialization",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "4460f0baf4fd99a2d65b1c8fec424ca05b5c566b",
    "submitter": {
        "id": 798,
        "url": "http://patchwork.dpdk.org/api/people/798/?format=api",
        "name": "Li, Xiaoyun",
        "email": "xiaoyun.li@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/20220729193042.2764633-4-xiaoyun.li@intel.com/mbox/",
    "series": [
        {
            "id": 24137,
            "url": "http://patchwork.dpdk.org/api/series/24137/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=24137",
            "date": "2022-07-29T19:30:32",
            "name": "introduce GVE PMD",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/24137/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/114453/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/114453/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 B7C00A00C4;\n\tFri, 29 Jul 2022 21:31:21 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 0E91B42C5B;\n\tFri, 29 Jul 2022 21:31:10 +0200 (CEST)",
            "from mga12.intel.com (mga12.intel.com [192.55.52.136])\n by mails.dpdk.org (Postfix) with ESMTP id B1E9F42C41\n for <dev@dpdk.org>; Fri, 29 Jul 2022 21:31:07 +0200 (CEST)",
            "from orsmga006.jf.intel.com ([10.7.209.51])\n by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 29 Jul 2022 12:31:07 -0700",
            "from silpixa00399779.ir.intel.com (HELO\n silpixa00399779.ger.corp.intel.com) ([10.237.223.111])\n by orsmga006.jf.intel.com with ESMTP; 29 Jul 2022 12:31:05 -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=1659123067; x=1690659067;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=sSHYyj3vBod3wSi+G4VatTwrf0vQH+qajLVq7tkk4pI=;\n b=MWXcr1yuWgI3u5J6dBhG/Y2jVbvX2ga29S/2q88oQ3wvna9w+G9j6Sxg\n F4qnilEyJ6Z/6qdocC/Hbtgpkqkg5rK7YbySXL4pSuhW9isa3J/mE6v3p\n 9lMlVaaWwoy71jSR+9Xe80oO9Vcy85Oh1H2jtSa7hQi/M88mMmBq3ZwCT\n PscUVM1gFc0kkZKriReFKBdrMh4gDiLVr9l15NOB4r7JfcRRperG2KocP\n 99cE+w0XhZiw6Xg1xWXJ09TL9I32OGMBKViCnFW+q9Y880OTkms+K7ea7\n ALWN+kYXhMfUP4AJqAX3AScee6ol+SakaFgkpnlOxht5PkHxjKGJro6lo w==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6400,9594,10423\"; a=\"268602917\"",
            "E=Sophos;i=\"5.93,201,1654585200\"; d=\"scan'208\";a=\"268602917\"",
            "E=Sophos;i=\"5.93,201,1654585200\"; d=\"scan'208\";a=\"577059536\""
        ],
        "X-ExtLoop1": "1",
        "From": "Xiaoyun Li <xiaoyun.li@intel.com>",
        "To": "junfeng.guo@intel.com, qi.z.zhang@intel.com, awogbemila@google.com,\n bruce.richardson@intel.com",
        "Cc": "dev@dpdk.org, Xiaoyun Li <xiaoyun.li@intel.com>,\n Haiyue Wang <haiyue.wang@intel.com>",
        "Subject": "[PATCH 03/10] net/gve: support device initialization",
        "Date": "Fri, 29 Jul 2022 19:30:35 +0000",
        "Message-Id": "<20220729193042.2764633-4-xiaoyun.li@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220729193042.2764633-1-xiaoyun.li@intel.com>",
        "References": "<20220729193042.2764633-1-xiaoyun.li@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 the fowllowing devops:\n  - dev_configure\n  - dev_start\n  - dev_stop\n  - dev_close\n\nSigned-off-by: Haiyue Wang <haiyue.wang@intel.com>\nSigned-off-by: Xiaoyun Li <xiaoyun.li@intel.com>\n---\n drivers/net/gve/gve.h        | 249 +++++++++++++++++++++++\n drivers/net/gve/gve_adminq.c |   1 +\n drivers/net/gve/gve_ethdev.c | 375 +++++++++++++++++++++++++++++++++++\n drivers/net/gve/meson.build  |  13 ++\n drivers/net/gve/version.map  |   3 +\n drivers/net/meson.build      |   1 +\n 6 files changed, 642 insertions(+)\n create mode 100644 drivers/net/gve/gve.h\n create mode 100644 drivers/net/gve/gve_ethdev.c\n create mode 100644 drivers/net/gve/meson.build\n create mode 100644 drivers/net/gve/version.map",
    "diff": "diff --git a/drivers/net/gve/gve.h b/drivers/net/gve/gve.h\nnew file mode 100644\nindex 0000000000..704c88983c\n--- /dev/null\n+++ b/drivers/net/gve/gve.h\n@@ -0,0 +1,249 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2022 Intel Corporation\n+ */\n+\n+#ifndef _GVE_H_\n+#define _GVE_H_\n+\n+#include <ethdev_driver.h>\n+#include <ethdev_pci.h>\n+#include <rte_ether.h>\n+\n+#include \"gve_desc.h\"\n+\n+#ifndef GOOGLE_VENDOR_ID\n+#define GOOGLE_VENDOR_ID\t0x1ae0\n+#endif\n+\n+#define GVE_DEV_ID\t\t0x0042\n+\n+#define GVE_REG_BAR\t0\n+#define GVE_DB_BAR\t2\n+\n+/* 1 for management, 1 for rx, 1 for tx */\n+#define GVE_MIN_MSIX\t\t3\n+\n+/* PTYPEs are always 10 bits. */\n+#define GVE_NUM_PTYPES\t1024\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_irq_db {\n+\trte_be32_t id;\n+} ____cacheline_aligned;\n+\n+struct gve_ptype {\n+\tuint8_t l3_type;  /* `gve_l3_type` in gve_adminq.h */\n+\tuint8_t l4_type;  /* `gve_l4_type` in gve_adminq.h */\n+};\n+\n+struct gve_ptype_lut {\n+\tstruct gve_ptype ptypes[GVE_NUM_PTYPES];\n+};\n+\n+enum gve_queue_format {\n+\tGVE_QUEUE_FORMAT_UNSPECIFIED = 0x0, /* default unspecified */\n+\tGVE_GQI_RDA_FORMAT\t     = 0x1, /* GQI Raw Addressing */\n+\tGVE_GQI_QPL_FORMAT\t     = 0x2, /* GQI Queue Page List */\n+\tGVE_DQO_RDA_FORMAT\t     = 0x3, /* DQO Raw Addressing */\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_lsc;\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+enum gve_state_flags_bit {\n+\tGVE_PRIV_FLAGS_ADMIN_QUEUE_OK\t\t= 1,\n+\tGVE_PRIV_FLAGS_DEVICE_RESOURCES_OK\t= 2,\n+\tGVE_PRIV_FLAGS_DEVICE_RINGS_OK\t\t= 3,\n+\tGVE_PRIV_FLAGS_NAPI_ENABLED\t\t= 4,\n+};\n+\n+static inline bool 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 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 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 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 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 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 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 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 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 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+#endif /* _GVE_H_ */\ndiff --git a/drivers/net/gve/gve_adminq.c b/drivers/net/gve/gve_adminq.c\nindex 8a724f12c6..438ca2070e 100644\n--- a/drivers/net/gve/gve_adminq.c\n+++ b/drivers/net/gve/gve_adminq.c\n@@ -5,6 +5,7 @@\n  * Copyright(C) 2022 Intel Corporation\n  */\n \n+#include \"gve.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..f10f273f7d\n--- /dev/null\n+++ b/drivers/net/gve/gve_ethdev.c\n@@ -0,0 +1,375 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2022 Intel Corporation\n+ */\n+#include <linux/pci_regs.h>\n+\n+#include \"gve.h\"\n+#include \"gve_adminq.h\"\n+#include \"gve_register.h\"\n+\n+#define GVE_VERSION\t\t\"1.3.0\"\n+#define GVE_VERSION_PREFIX\t\"GVE-\"\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\\n\", 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_INIT_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_INIT_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_INIT_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_INIT_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_INIT_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_INIT_LOG(ERR, \"Failed to map pci bar!\\n\");\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_INIT_LOG(ERR, \"Failed to map doorbell bar!\\n\");\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_INIT_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+\teth_dev->data->mac_addrs = NULL;\n+\n+\tgve_teardown_priv_resources(priv);\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 | RTE_PCI_DRV_INTR_LSC,\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_init, init, NOTICE);\n+RTE_LOG_REGISTER_SUFFIX(gve_logtype_driver, driver, NOTICE);\ndiff --git a/drivers/net/gve/meson.build b/drivers/net/gve/meson.build\nnew file mode 100644\nindex 0000000000..9a22cc9abe\n--- /dev/null\n+++ b/drivers/net/gve/meson.build\n@@ -0,0 +1,13 @@\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+        'gve_adminq.c',\n+        'gve_ethdev.c',\n+)\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 e35652fe63..f1a0ee2cef 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": [
        "03/10"
    ]
}