Change gve_driver_info fields to report DPDK as OS type and DPDK RTE
version as OS version, reserving driver_version fields for GVE driver
version based on features.

Depends-on: series-27687

Signed-off-by: Rushil Gupta <rush...@google.com>
Signed-off-by: Joshua Washington <joshw...@google.com>
Signed-off-by: Junfeng Guo <junfeng....@intel.com>
Signed-off-by: Jeroen de Borst <jeroe...@google.com>
---
 drivers/net/gve/base/gve.h        |  3 --
 drivers/net/gve/base/gve_adminq.c | 19 +++++++++
 drivers/net/gve/base/gve_adminq.h | 49 ++++++++++++++++++++++-
 drivers/net/gve/base/gve_osdep.h  | 36 +++++++++++++++++
 drivers/net/gve/gve_ethdev.c      | 65 +++++++++++++++++++++++++------
 drivers/net/gve/gve_ethdev.h      |  2 +-
 drivers/net/gve/gve_version.c     | 14 +++++++
 drivers/net/gve/gve_version.h     | 25 ++++++++++++
 drivers/net/gve/meson.build       |  1 +
 9 files changed, 198 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/gve/gve_version.c
 create mode 100644 drivers/net/gve/gve_version.h

diff --git a/drivers/net/gve/base/gve.h b/drivers/net/gve/base/gve.h
index 2dc4507acb..89f9654a72 100644
--- a/drivers/net/gve/base/gve.h
+++ b/drivers/net/gve/base/gve.h
@@ -8,9 +8,6 @@
 
 #include "gve_desc.h"
 
-#define GVE_VERSION            "1.3.0"
-#define GVE_VERSION_PREFIX     "GVE-"
-
 #ifndef GOOGLE_VENDOR_ID
 #define GOOGLE_VENDOR_ID       0x1ae0
 #endif
diff --git a/drivers/net/gve/base/gve_adminq.c 
b/drivers/net/gve/base/gve_adminq.c
index e745b709b2..2e5099a5b0 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -401,6 +401,9 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
        case GVE_ADMINQ_GET_PTYPE_MAP:
                priv->adminq_get_ptype_map_cnt++;
                break;
+       case GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY:
+               priv->adminq_verify_driver_compatibility_cnt++;
+               break;
        default:
                PMD_DRV_LOG(ERR, "unknown AQ command opcode %d", opcode);
        }
@@ -465,6 +468,22 @@ int gve_adminq_configure_device_resources(struct gve_priv 
*priv,
        return gve_adminq_execute_cmd(priv, &cmd);
 }
 
+int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
+                                          u64 driver_info_len,
+                                          dma_addr_t driver_info_addr)
+{
+       union gve_adminq_command cmd;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.opcode = cpu_to_be32(GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY);
+       cmd.verify_driver_compatibility = (struct 
gve_adminq_verify_driver_compatibility) {
+               .driver_info_len = cpu_to_be64(driver_info_len),
+               .driver_info_addr = cpu_to_be64(driver_info_addr),
+       };
+
+       return gve_adminq_execute_cmd(priv, &cmd);
+}
+
 int gve_adminq_deconfigure_device_resources(struct gve_priv *priv)
 {
        union gve_adminq_command cmd;
diff --git a/drivers/net/gve/base/gve_adminq.h 
b/drivers/net/gve/base/gve_adminq.h
index 05550119de..edac32f031 100644
--- a/drivers/net/gve/base/gve_adminq.h
+++ b/drivers/net/gve/base/gve_adminq.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: MIT
  * Google Virtual Ethernet (gve) driver
- * Copyright (C) 2015-2022 Google, Inc.
+ * Copyright (C) 2015-2023 Google, Inc.
  */
 
 #ifndef _GVE_ADMINQ_H
@@ -23,6 +23,7 @@ enum gve_adminq_opcodes {
        GVE_ADMINQ_REPORT_STATS                 = 0xC,
        GVE_ADMINQ_REPORT_LINK_SPEED            = 0xD,
        GVE_ADMINQ_GET_PTYPE_MAP                = 0xE,
+       GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY  = 0xF,
 };
 
 /* Admin queue status codes */
@@ -145,6 +146,47 @@ enum gve_sup_feature_mask {
 };
 
 #define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0
+enum gve_driver_capbility {
+       gve_driver_capability_gqi_qpl = 0,
+       gve_driver_capability_gqi_rda = 1,
+       gve_driver_capability_dqo_qpl = 2, /* reserved for future use */
+       gve_driver_capability_dqo_rda = 3,
+};
+
+#define GVE_CAP1(a) BIT((int)a)
+#define GVE_CAP2(a) BIT(((int)a) - 64)
+#define GVE_CAP3(a) BIT(((int)a) - 128)
+#define GVE_CAP4(a) BIT(((int)a) - 192)
+
+#define GVE_DRIVER_CAPABILITY_FLAGS1 \
+       (GVE_CAP1(gve_driver_capability_gqi_qpl) | \
+        GVE_CAP1(gve_driver_capability_gqi_rda) | \
+        GVE_CAP1(gve_driver_capability_dqo_rda))
+
+#define GVE_DRIVER_CAPABILITY_FLAGS2 0x0
+#define GVE_DRIVER_CAPABILITY_FLAGS3 0x0
+#define GVE_DRIVER_CAPABILITY_FLAGS4 0x0
+
+struct gve_driver_info {
+       u8 os_type;     /* 0x05 = DPDK */
+       u8 driver_major;
+       u8 driver_minor;
+       u8 driver_sub;
+       __be32 os_version_major;
+       __be32 os_version_minor;
+       __be32 os_version_sub;
+       __be64 driver_capability_flags[4];
+       u8 os_version_str1[OS_VERSION_STRLEN];
+       u8 os_version_str2[OS_VERSION_STRLEN];
+};
+
+struct gve_adminq_verify_driver_compatibility {
+       __be64 driver_info_len;
+       __be64 driver_info_addr;
+};
+
+GVE_CHECK_STRUCT_LEN(16,  gve_adminq_verify_driver_compatibility);
+
 
 struct gve_adminq_configure_device_resources {
        __be64 counter_array;
@@ -345,6 +387,8 @@ union gve_adminq_command {
                        struct gve_adminq_report_stats report_stats;
                        struct gve_adminq_report_link_speed report_link_speed;
                        struct gve_adminq_get_ptype_map get_ptype_map;
+                       struct gve_adminq_verify_driver_compatibility
+                               verify_driver_compatibility;
                };
        };
        u8 reserved[64];
@@ -378,4 +422,7 @@ struct gve_ptype_lut;
 int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
                                 struct gve_ptype_lut *ptype_lut);
 
+int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
+                                          u64 driver_info_len,
+                                          dma_addr_t driver_info_addr);
 #endif /* _GVE_ADMINQ_H */
diff --git a/drivers/net/gve/base/gve_osdep.h b/drivers/net/gve/base/gve_osdep.h
index 7cb73002f4..a5efa8543e 100644
--- a/drivers/net/gve/base/gve_osdep.h
+++ b/drivers/net/gve/base/gve_osdep.h
@@ -21,9 +21,14 @@
 #include <rte_malloc.h>
 #include <rte_memcpy.h>
 #include <rte_memzone.h>
+#include <rte_version.h>
 
 #include "../gve_logs.h"
 
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+
 typedef uint8_t u8;
 typedef uint16_t u16;
 typedef uint32_t u32;
@@ -69,6 +74,12 @@ typedef rte_iova_t dma_addr_t;
 
 #define msleep(ms)             rte_delay_ms(ms)
 
+#define OS_VERSION_STRLEN 128
+struct os_version_string {
+       char os_version_str1[OS_VERSION_STRLEN];
+       char os_version_str2[OS_VERSION_STRLEN];
+};
+
 /* These macros are used to generate compilation errors if a struct/union
  * is not exactly the correct length. It gives a divide by zero error if
  * the struct/union is not of the correct size, otherwise it creates an
@@ -79,6 +90,12 @@ typedef rte_iova_t dma_addr_t;
 #define GVE_CHECK_UNION_LEN(n, X) enum gve_static_asset_enum_##X \
        { gve_static_assert_##X = (n) / ((sizeof(union X) == (n)) ? 1 : 0) }
 
+#ifndef LINUX_VERSION_MAJOR
+#define LINUX_VERSION_MAJOR (((LINUX_VERSION_CODE) >> 16) & 0xff)
+#define LINUX_VERSION_SUBLEVEL (((LINUX_VERSION_CODE) >> 8) & 0xff)
+#define LINUX_VERSION_PATCHLEVEL ((LINUX_VERSION_CODE) & 0xff)
+#endif
+
 static __rte_always_inline u8
 readb(volatile void *addr)
 {
@@ -156,4 +173,23 @@ gve_free_dma_mem(struct gve_dma_mem *mem)
        mem->pa = 0;
 }
 
+static inline void
+populate_driver_version_strings(struct os_version_string *os_version_str)
+{
+#ifdef __linux__
+       struct utsname uts;
+       if (uname(&uts) >= 0) {
+               /* release */
+               rte_strscpy(os_version_str->os_version_str1, uts.release,
+                       sizeof(os_version_str->os_version_str1));
+               /* version */
+               rte_strscpy(os_version_str->os_version_str2, uts.version,
+                       sizeof(os_version_str->os_version_str2));
+       }
+#else
+       /* gVNIC is currently not supported on OS like FreeBSD */
+       RTE_SET_USED(os_version_str);
+#endif
+}
+
 #endif /* _GVE_OSDEP_H_ */
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index cf28a4a3b7..1d6e134fff 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -5,21 +5,13 @@
 #include "gve_ethdev.h"
 #include "base/gve_adminq.h"
 #include "base/gve_register.h"
-
-const char gve_version_str[] = GVE_VERSION;
-static const char gve_version_prefix[] = GVE_VERSION_PREFIX;
+#include "base/gve_osdep.h"
+#include "gve_version.h"
 
 static void
 gve_write_version(uint8_t *driver_version_register)
 {
-       const char *c = gve_version_prefix;
-
-       while (*c) {
-               writeb(*c, driver_version_register);
-               c++;
-       }
-
-       c = gve_version_str;
+       const char *c = gve_version_string();
        while (*c) {
                writeb(*c, driver_version_register);
                c++;
@@ -265,6 +257,52 @@ gve_dev_close(struct rte_eth_dev *dev)
        return err;
 }
 
+static int
+gve_verify_driver_compatibility(struct gve_priv *priv)
+{
+       const struct rte_memzone *driver_info_bus;
+       struct gve_driver_info *driver_info;
+       int err;
+
+       driver_info_bus = 
rte_memzone_reserve_aligned("verify_driver_compatibility",
+                                                     sizeof(struct 
gve_driver_info),
+                                                     rte_socket_id(),
+                                                     RTE_MEMZONE_IOVA_CONTIG, 
PAGE_SIZE);
+       if (driver_info_bus == NULL) {
+               PMD_DRV_LOG(ERR,
+                           "Could not alloc memzone for driver compatibility");
+               return -ENOMEM;
+       }
+       driver_info = (struct gve_driver_info *)driver_info_bus->addr;
+       *driver_info = (struct gve_driver_info) {
+               .os_type = 5, /* DPDK */
+               .driver_major = GVE_VERSION_MAJOR,
+               .driver_minor = GVE_VERSION_MINOR,
+               .driver_sub = GVE_VERSION_SUB,
+               .os_version_major = cpu_to_be32(DPDK_VERSION_MAJOR),
+               .os_version_minor = cpu_to_be32(DPDK_VERSION_MINOR),
+               .os_version_sub = cpu_to_be32(DPDK_VERSION_SUB),
+               .driver_capability_flags = {
+                       cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS1),
+                       cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS2),
+                       cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS3),
+                       cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS4),
+               },
+       };
+
+       populate_driver_version_strings((struct os_version_string 
*)&driver_info->os_version_str1);
+
+       err = gve_adminq_verify_driver_compatibility(priv,
+               sizeof(struct gve_driver_info), (dma_addr_t)driver_info_bus);
+
+       /* It's ok if the device doesn't support this */
+       if (err == -EOPNOTSUPP)
+               err = 0;
+
+       rte_memzone_free(driver_info_bus);
+       return err;
+}
+
 static int
 gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
@@ -672,6 +710,11 @@ gve_init_priv(struct gve_priv *priv, bool 
skip_describe_device)
                PMD_DRV_LOG(ERR, "Failed to alloc admin queue: err=%d", err);
                return err;
        }
+       err = gve_verify_driver_compatibility(priv);
+       if (err) {
+               PMD_DRV_LOG(ERR, "Could not verify driver compatibility: 
err=%d", err);
+               goto free_adminq;
+       }
 
        if (skip_describe_device)
                goto setup_device;
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 42a02cf5d4..23ccff37d3 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -222,7 +222,7 @@ struct gve_priv {
        uint32_t adminq_report_stats_cnt;
        uint32_t adminq_report_link_speed_cnt;
        uint32_t adminq_get_ptype_map_cnt;
-
+       uint32_t adminq_verify_driver_compatibility_cnt;
        volatile uint32_t state_flags;
 
        /* Gvnic device link speed from hypervisor. */
diff --git a/drivers/net/gve/gve_version.c b/drivers/net/gve/gve_version.c
new file mode 100644
index 0000000000..7eaa689d90
--- /dev/null
+++ b/drivers/net/gve/gve_version.c
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: MIT
+ * Google Virtual Ethernet (gve) driver
+ * Copyright (C) 2015-2023 Google, Inc.
+ */
+#include "gve_version.h"
+
+const char *gve_version_string(void)
+{
+       static char gve_version[10];
+       snprintf(gve_version, sizeof(gve_version), "%s%d.%d.%d",
+               GVE_VERSION_PREFIX, GVE_VERSION_MAJOR, GVE_VERSION_MINOR,
+               GVE_VERSION_SUB);
+       return gve_version;
+}
diff --git a/drivers/net/gve/gve_version.h b/drivers/net/gve/gve_version.h
new file mode 100644
index 0000000000..9af6a00568
--- /dev/null
+++ b/drivers/net/gve/gve_version.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: MIT
+ * Google Virtual Ethernet (gve) driver
+ * Copyright (C) 2015-2023 Google, Inc.
+ */
+
+#ifndef _GVE_VERSION_H_
+#define _GVE_VERSION_H_
+
+#include <rte_version.h>
+
+#define GVE_VERSION_PREFIX "DPDK-"
+#define GVE_VERSION_MAJOR 1
+#define GVE_VERSION_MINOR 0
+#define GVE_VERSION_SUB 0
+
+#define DPDK_VERSION_MAJOR (100 * RTE_VER_YEAR + RTE_VER_MONTH)
+#define DPDK_VERSION_MINOR RTE_VER_MINOR
+#define DPDK_VERSION_SUB RTE_VER_RELEASE
+
+
+const char *
+gve_version_string(void);
+
+
+#endif /* GVE_VERSION_H */
diff --git a/drivers/net/gve/meson.build b/drivers/net/gve/meson.build
index af0010c01c..a37c4bafa2 100644
--- a/drivers/net/gve/meson.build
+++ b/drivers/net/gve/meson.build
@@ -12,5 +12,6 @@ sources = files(
         'gve_rx.c',
         'gve_tx.c',
         'gve_ethdev.c',
+        'gve_version.c',
 )
 includes += include_directories('base')
-- 
2.40.0.634.g4ca3ef3211-goog

Reply via email to